Compare commits

...

50 commits

Author SHA1 Message Date
Ivan Pozdeev eda64556af
1.4.0
Some checks failed
tests / tests (ubuntu-22.04) (push) Has been cancelled
tests / tests (ubuntu-24.04) (push) Has been cancelled
tests / tests (macos-14) (push) Has been cancelled
tests / tests (macos-15) (push) Has been cancelled
tests / tests (macos-15-intel) (push) Has been cancelled
tests / tests (macos-26) (push) Has been cancelled
2026-04-29 08:24:00 +03:00
Sam Doran 37ab83f1b0
Improve performance and output of pyenv virtualenvs (#502)
* With 160 envs, cuts time from ~14s to ~2.5s
* Change the output to be more like `pyenv-versions'
* Shellcheck fixes
* virtualenv: Only show non-envs for completion since env engines don't support piggy-backing envs
* Remove dead/unused code
* Fix IFS handling
`IFS=: <command>' doesn't apply that IFS to expansions in <command>,
it has to be set separately earlier
* Adjust and refactor tests

---------

Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
2026-04-29 08:08:52 +03:00
Chris Caldwell 99d35f201c
Fix POSIX sh (dash) compatibility in pyenv-virtualenv-init (#526)
* Refactor cache code generation
* Don't generate prompt_command for non bash/zsh/fish

---------

Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
2026-04-21 18:53:01 +03:00
Ivan Pozdeev 6a832cacbb
CI: use macos-26
the Github runner is out of beta
2026-04-17 22:54:31 +03:00
Ivan Pozdeev 90dfbcad93
1.3.0 2026-03-25 23:46:29 +03:00
Ivan Pozdeev f046752219
Reformat changelog to conform to Pyenv and Github release notes 2026-03-25 23:45:47 +03:00
Jake Lodwick 72cb35b2b4
Drastically speed up precommand hook by caching active version to skip redundant activate calls (#523) 2026-03-25 23:33:43 +03:00
native-api 38f3333f3a
Merge pull request #520 from native-api/prevent-deletion-of-contents-in-generic-prefix-env-var
CI: tests: use Bats 1.10; support concurrent, out-of-order and multiple-times execution of stub commands; fix race condition between concurrent stubs
2025-12-18 03:52:21 +03:00
Ivan Pozdeev 10c8ace3c3
Fix a race condition between concurrently executing stubs 2025-12-18 03:47:17 +03:00
Ivan Pozdeev 7d9840478c
stub: -unnecessary indirection 2025-12-18 03:47:16 +03:00
Ivan Pozdeev bf7d3b0584
stub, test_helper: support concurrent, out-of-order and multiple-times stub command execution 2025-12-18 03:46:38 +03:00
Ivan Pozdeev dd2ad3ee65
stub: dumping the plan vars is redundant
They proved to not be useful for diagnostics
2025-12-18 03:30:05 +03:00
Ivan Pozdeev 4785e89a3b
Use Bats v1.10.0 2025-12-18 03:06:38 +03:00
native-api b83e2c3c83
CI: - commented-out code; - macos-11 workaround (#521) 2025-12-18 00:41:30 +03:00
Ivan Pozdeev b5c88a7a15
1.2.6 2025-12-14 18:41:47 +03:00
SabriRamadanTNG 64233612fb
Prevent loss of data on virtualenv-delete -f if the env doesn't exist and the PREFIX envvar is set elsewhere (#518)
* Rename the PREFIX var just in case as too generic

Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
2025-12-13 20:05:26 +03:00
native-api 4d37a6e477
Convert issue template to new Github format (#519)
* Convert issue template to new Github format

the old format seems to be dropped altogether now

[no ci]
2025-12-13 17:19:41 +03:00
Ivan Pozdeev f5b2602597
CI: change macos-13 to macos-15-intel 2025-12-11 14:47:13 +03:00
Charlie (cshen.dev) 387f627464
docs: fix the link to Pyenv shell setup steps (#516) 2025-09-22 08:36:00 +03:00
Seokhee Park 4b3f5f8468
docs: add WSL note about core.autocrlf to prevent CRLF issues (#512) 2025-05-17 10:19:25 +03:00
Ivan Pozdeev 3057e1549b [CI] Update environments
ubuntu-20.04 is dropped, macos-15 is available
2025-05-06 19:14:54 +03:00
Jason N. White aa9b8e9a5a
Update LICENSE, fix license year (#499)
Some checks failed
tests / tests (ubuntu-22.04) (push) Failing after 1s
tests / tests (macos-13) (push) Has been cancelled
tests / tests (macos-14) (push) Has been cancelled
tests / tests (ubuntu-20.04) (push) Has been cancelled
Signed-off-by: JasonnnW3000 <sufssl04@gmail.com>
2025-01-01 20:46:21 +03:00
native-api e8c8fd9b84
Fix errorneously creating a symlink inside env directory if running with -f (#496)
Some checks failed
tests / tests (macos-13) (push) Has been cancelled
tests / tests (macos-14) (push) Has been cancelled
tests / tests (ubuntu-20.04) (push) Has been cancelled
tests / tests (ubuntu-22.04) (push) Failing after 0s
2024-12-08 23:30:27 +03:00
native-api db299cada3
Fix confusing activate/deactivate error messages (#495) 2024-12-08 21:43:35 +03:00
native-api c6bb0694bf
Fix pyenv-virtualenv using a different Python version in a conda environment (#492)
Some checks failed
tests / tests (ubuntu-22.04) (push) Failing after 0s
tests / tests (macos-13) (push) Has been cancelled
tests / tests (macos-14) (push) Has been cancelled
tests / tests (ubuntu-20.04) (push) Has been cancelled
Allow output checking with wildcards
2024-11-25 00:54:05 +03:00
Zac Holland 28cd9be54e
README: fix and distinguish syntax highlighting in Bash vs Fish snippets (#489)
Some checks failed
tests / tests (ubuntu-22.04) (push) Failing after 0s
tests / tests (macos-13) (push) Has been cancelled
tests / tests (macos-14) (push) Has been cancelled
tests / tests (ubuntu-20.04) (push) Has been cancelled
Co-authored-by: native-api <vano@mail.mipt.ru>
2024-09-18 22:08:52 +03:00
Jovier Jimenez d4c9655e26
Add prompt customization (#476)
Some checks failed
tests / tests (ubuntu-22.04) (push) Failing after 1s
tests / tests (macos-13) (push) Has been cancelled
tests / tests (macos-14) (push) Has been cancelled
tests / tests (ubuntu-20.04) (push) Has been cancelled
2024-09-15 09:40:44 +03:00
Ivan Pozdeev e9b88cc366 1.2.4
Some checks failed
tests / tests (ubuntu-22.04) (push) Failing after 1s
tests / tests (macos-13) (push) Has been cancelled
tests / tests (macos-14) (push) Has been cancelled
tests / tests (ubuntu-20.04) (push) Has been cancelled
2024-07-22 00:37:02 +03:00
native-api d811b3fef2
Merge pull request #484 from native-api/pyenv_latest_f
Reflect pyenv-latest switch change in 2.4.8
2024-07-22 00:34:28 +03:00
Ivan Pozdeev d6756cab9b CI: bump macos
Github dropped macos-11, introduced 13 and 14
2024-07-22 00:32:59 +03:00
Ivan Pozdeev 6179ac76c4 Reflect pyenv-latest switch change in 2.4.8 2024-07-21 23:31:47 +03:00
Alex Galonsky cf45718a1b
README: Remove dollar signs from commands that are meant to be copied (#481)
Some checks failed
tests / tests (ubuntu-22.04) (push) Has been cancelled
tests / tests (macos-11) (push) Has been cancelled
tests / tests (macos-12) (push) Has been cancelled
tests / tests (ubuntu-20.04) (push) Has been cancelled
2024-06-27 20:16:45 +03:00
native-api 37917069ec
Fix failing to detect -m venv when "python" is not provided by the distro (#479) 2024-04-10 00:14:13 +03:00
Ivan Pozdeev b90bd92853 1.2.3 2024-04-07 22:59:10 +03:00
Ivan Pozdeev 33f54ecad9 Add maintenance guide 2024-04-07 22:50:45 +03:00
native-api f8469a1c67
Merge pull request #478 from native-api/3drparty_venv_over_ours
Don't activate if a 3rd-party venv is activated over ours
2024-04-03 23:12:47 +03:00
Ivan Pozdeev ac28398fc0 Don't activate if a 3rd-party virtualenv is active over ours 2024-04-03 21:09:22 +03:00
Ivan Pozdeev 45a28ac094 bump stub and stub fns to Pyenv version 2024-04-03 21:09:22 +03:00
Romir K 0f83c33a3b
Add fish prompt changing (#475) 2024-02-12 12:58:27 +03:00
John HU 2b2b87a25a
Bump pyenv-virtualenv reporting version to match release (#471)
The latest release so far (Dec 2023) is 1.2.2, but the version reported is still 1.2.1:
https://github.com/pyenv/pyenv-virtualenv/releases/tag/v1.2.2
2023-12-06 06:56:52 +03:00
Jason Mobarak 38a6561f96
fix: add colorize helper (#470) 2023-11-29 11:37:00 +03:00
native-api c85c1c9ed5
Link python*-config into VE (#460)
Required to build binaries that link against Python.
Carl Meyer, the champion for PEP 0405, has confirmed that there isn't a particular reason why `venv` doesn't do that.
2023-06-27 01:36:04 +03:00
Elijah Lynn cd6a51ad68
Add fish install oneliner (#322)
Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
2023-04-17 00:01:19 +03:00
Marcin Konowalczyk 85d8c5aabf
More helpful error message when env's base version is not installed (#454) 2023-04-10 21:42:47 +03:00
Josh French fca12418ca
Add activate/deactivate hooks (#452) 2023-03-22 20:39:55 +03:00
Jack McIvor 13bc1877ef
Update PYENV_VIRTUALENV_VERSION (#449)
Co-authored-by: Jack McIvor <j.mcivor@draftkings.com>
2023-02-07 19:37:47 +03:00
Ivan Pozdeev a724aaa149 Merge branch 'master' of https://github.com/pyenv/pyenv-virtualenv 2023-02-01 00:27:32 +03:00
Ivan Pozdeev f4162706d8 Remove Bountysource from advertized donation sources
Same as in Pyenv, as it's gone rogue
2023-02-01 00:27:13 +03:00
native-api 77a7644ff7
Remove prompt deprecation warning (#447)
Prompt removal was never done and is not planned anymore
2023-01-31 23:14:52 +03:00
Ivan Pozdeev 826f3fbe6f ISSUE_TEMPLATE.md: Add Zsh PS4 2023-01-31 23:02:54 +03:00
35 changed files with 1482 additions and 436 deletions

2
.github/FUNDING.yml vendored
View file

@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
liberapay: # Replace with a single Liberapay username liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username otechie: # Replace with a single Otechie username
custom: ['https://www.bountysource.com/teams/pyenv-virtualenv/issues'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View file

@ -1,17 +1,30 @@
Too many issues will kill our team's development velocity, drastically. ---
Make sure you have checked all steps below. name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
### Prerequisite ### Prerequisite
* [ ] Make sure your problem is not listed in [the common build problems](https://github.com/pyenv/pyenv/wiki/Common-build-problems).
* [ ] Make sure no duplicated issue has already been reported in [the pyenv-virtualenv issues](https://github.com/pyenv/pyenv-virtualenv/issues). You should look in closed issues, too. * [ ] Make sure no duplicated issue has already been reported in [the pyenv-virtualenv issues](https://github.com/pyenv/pyenv-virtualenv/issues). You should look in closed issues, too.
* [ ] Make sure you are not asking us to help solving your specific issue. * [ ] Make sure you are reporting a problem in Pyenv-Virtualenv and not seeking consultation with Pyenv-Virtualenv use.
* GitHub issues is opened mainly for development purposes. If you want to ask someone to help solving your problem, go to some community site like [Gitter](https://gitter.im/yyuu/pyenv), [StackOverflow](https://stackoverflow.com/questions/tagged/pyenv), etc. * GitHub issues are intended mainly for Pyenv-Virtualenv development purposes. If you are seeking help with Pyenv-Virtualenv use, check [Pyenv-Virtualenv documentation](https://github.com/pyenv/pyenv-virtualenv?tab=readme-ov-file#usage), go to a user community site like [Gitter](https://gitter.im/yyuu/pyenv), [StackOverflow](https://stackoverflow.com/questions/tagged/pyenv), etc, or to [Discussions](https://github.com/orgs/pyenv/discussions).
* [ ] Make sure your problem is not derived from packaging (e.g. [Homebrew](https://brew.sh)). * [ ] Make sure your problem is not derived from packaging (e.g. [Homebrew](https://brew.sh)).
* Please refer to the package documentation for the installation issues, etc. * Please refer to the package documentation for the installation issues, etc.
* [ ] Make sure your problem is not derived from other plugins. * [ ] Make sure your problem is not derived from other plugins.
* This repository is maintaining the `pyenv-virtualenv` plugin only. Please refrain from reporting issues of other plugins here. * This repository is maintaining the `pyenv-virtualenv` plugin only. Please refrain from reporting issues of other plugins here.
### Description ### Describe the bug
A clear and concise description of what the bug is.
Do specify what the expected behaviour is if that's not obvious from the bug's nature.
#### Reproduction steps
Listing the commands to run in a new console session and their output is usually sufficient.
Please use a Markdown code block (three backticks on a line by themselves before and after the text) to denote a console output excerpt.
#### Diagnostic details
- [ ] Platform information (e.g. Ubuntu Linux 20.04): - [ ] Platform information (e.g. Ubuntu Linux 20.04):
- [ ] OS architecture (e.g. amd64): - [ ] OS architecture (e.g. amd64):
- [ ] pyenv version: - [ ] pyenv version:
@ -21,8 +34,12 @@ Make sure you have checked all steps below.
- [ ] Please attach the debug log of a faulty Pyenv invocation as a gist - [ ] Please attach the debug log of a faulty Pyenv invocation as a gist
* If the problem happens in a Pyenv invocation, you can turn on debug logging by setting `PYENV_DEBUG=1`, e.g. `env PYENV_DEBUG=1 pyenv install -v 3.6.4` * If the problem happens in a Pyenv invocation, you can turn on debug logging by setting `PYENV_DEBUG=1`, e.g. `env PYENV_DEBUG=1 pyenv install -v 3.6.4`
* If the problem happens outside of a Pyenv invocation, get the debug log like this: * If the problem happens outside of a Pyenv invocation, get the debug log like this:
``` ```bash
# for Bash
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
# for Zsh
export PS4='+(%x:%I): %N(%i): '
set -x set -x
<reproduce the problem> <reproduce the problem>
set +x set +x

View file

@ -0,0 +1,24 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Describe the intended use case**
* What your general environment is if it's relevant to the feature request and is not a generic console with a typical Pyenv installation (CI, server with a custom setup, cloud environment, IDE)
* What you are trying to achieve
* What specifically you are doing for that regarding Pyenv
* Where you are stuck
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
[ ] In particular, did you consider [writing a plugin](https://github.com/pyenv/pyenv/blob/master/README.md#pyenv-plugins)? Note that if your plugin has general applicability, you can publish it in the 3rd-party plugin catalog on the Pyenv Wiki as per the link above.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -7,31 +7,13 @@ jobs:
matrix: matrix:
os: os:
- ubuntu-22.04 - ubuntu-22.04
- ubuntu-20.04 - ubuntu-24.04
- macos-12 - macos-14
- macos-11 - macos-15
- macos-15-intel
- macos-26
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
# Normally, we would use the superbly maintained... - run: git clone https://github.com/bats-core/bats-core.git --depth=1 -b v1.10.0 bats
# - uses: actions/setup-python@v2
# with:
# python-version: ${{ matrix.python-version }}
# ... but in the repo, we want to test pyenv builds on Ubuntu
# - run: |
# sudo apt-get install -y build-essential libssl-dev zlib1g-dev libbz2-dev \
# libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
# xz-utils tk-dev libffi-dev liblzma-dev python-openssl git
# https://github.com/pyenv/pyenv#installation
#- env:
# PYENV_ROOT: /home/runner/work/pyenv/pyenv
# run: |
# echo $PYENV_ROOT
# echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
# macos-11 Github Actions env has an old `readlink` and lacks `greadlink` which causes Bats to break
- run: |
if [[ $RUNNER_OS == "macOS" ]] && [[ $(sw_vers -productVersion | awk -F. '{print $1}') -lt 12 ]]; then
brew install coreutils
fi
- run: git clone https://github.com/bats-core/bats-core.git --depth=1 -b v1.2.0 bats
- run: bats/bin/bats --tap test - run: bats/bin/bats --tap test

View file

@ -1,62 +1,131 @@
## Version History ## Version History
#### 1.1.5 ## v1.4.0
* Fix POSIX sh (dash) compatibility in pyenv-virtualenv-init by @chrisolof in https://github.com/pyenv/pyenv-virtualenv/pull/526
* Improve performance and output of `pyenv virtualenvs` by @samdoran in https://github.com/pyenv/pyenv-virtualenv/pull/502
## v1.3.0
* CI: cleanup by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/521
* CI: tests: use Bats 1.10; support concurrent, out-of-order and multiple-times execution of stub commands; fix race condition between concurrent stubs by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/520
* Drastically speed up precommand hook by caching active version to skip redundant `activate` calls by @jakelodwick in https://github.com/pyenv/pyenv-virtualenv/pull/523
## v1.2.6
* Fix changelog and version numbers
## v1.2.5
* Add prompt customization by @jimenezj8 in https://github.com/pyenv/pyenv-virtualenv/pull/476
* README: fix and distinguish syntax highlighting in Bash vs Fish snippets by @diericx in https://github.com/pyenv/pyenv-virtualenv/pull/489
* Fix pyenv-virtualenv using a different Python version in a conda environment by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/492
* Fix confusing activate/deactivate error messages when Pyenv is not installed as a shell function by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/495
* Fix errorneously creating a symlink inside env directory if running w… by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/496
* Update LICENSE, fix copyright license year by @JasonnnW3000 in https://github.com/pyenv/pyenv-virtualenv/pull/499
* docs: add WSL note about core.autocrlf to prevent CRLF issues by @stoneHee99 in https://github.com/pyenv/pyenv-virtualenv/pull/512
* docs: fix the link to Pyenv shell setup steps by @cshen-dev in https://github.com/pyenv/pyenv-virtualenv/pull/516
* Convert issue template to new Github format by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/519
* Prevent loss of data on `virtualenv-delete -f` if the env doesn't exist and the PREFIX envvar is set elsewhere by @SabriRamadanTNG in https://github.com/pyenv/pyenv-virtualenv/pull/518
## v1.2.4
* Fix failing to detect `-m venv` when "python" is not provided by the distro by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/479
* README: Remove dollar signs from commands that are meant to be copied by @galonsky in https://github.com/pyenv/pyenv-virtualenv/pull/481
* Reflect pyenv-latest switch change in 2.4.8 by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/484
## v1.2.3
* Fix: add `colorize` helper by @silverjam in https://github.com/pyenv/pyenv-virtualenv/pull/470
* Bump pyenv-virtualenv reporting version to match release by @ushuz in https://github.com/pyenv/pyenv-virtualenv/pull/471
* Add fish prompt changing by @romirk in https://github.com/pyenv/pyenv-virtualenv/pull/475
* Don't activate if a 3rd-party venv is activated over ours by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/478
## v1.2.2
* Prompt removal was never done and is not planned anymore by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/447
* Update PYENV_VIRTUALENV_VERSION by @jack-mcivor in https://github.com/pyenv/pyenv-virtualenv/pull/449
* Add activate/deactivate hooks by @joshfrench in https://github.com/pyenv/pyenv-virtualenv/pull/452
* More helpful error message when requesting a nonexistent base version by @MarcinKonowalczyk in https://github.com/pyenv/pyenv-virtualenv/pull/454
* Add fish install oneliner by @ElijahLynn in https://github.com/pyenv/pyenv-virtualenv/pull/322
* Link python*-config into VE by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/460
## v1.2.1
* Support prefixes resolved by pyenv-latest as base version names by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/446
## v1.2.0
* ~/.*rc should be modified instead of ~/.*profile by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/384
* Fixes #394 - update pyenv virtualenvs to list virtualenvs start with dot prefixes by @Gauravtalreja1 in https://github.com/pyenv/pyenv-virtualenv/pull/395
* Fix installation steps to allow for Pyenv 2 by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/388
* Fix get-pip.py URLs for older versions of Python by @jivanf in https://github.com/pyenv/pyenv-virtualenv/pull/403
* Add (y/N) prompt help text by @sh-cho in https://github.com/pyenv/pyenv-virtualenv/pull/404
* perf(sh-activate): avoid a pyenv-version-name call by @scop in https://github.com/pyenv/pyenv-virtualenv/pull/380
* Fix unbound variable errors when running `pyenv activate` with `set -u` Use default empty value. This fixes #422. by @ackalker in https://github.com/pyenv/pyenv-virtualenv/pull/423
* Fix another unbound variable error by @ackalker in https://github.com/pyenv/pyenv-virtualenv/pull/424
* Update `get-pip.py` URLs in `pyenv-virtualenv` by @mcdonnnj in https://github.com/pyenv/pyenv-virtualenv/pull/426
* Deduplicate shims in $PATH for the fish shell during initialization by @ericvw in https://github.com/pyenv/pyenv-virtualenv/pull/430
* Upgrade uninstall hook after pyenv/pyenv#2432 by @laggardkernel in https://github.com/pyenv/pyenv-virtualenv/pull/438
* Stop delete force failing when virtualenv does not exist by @eganjs in https://github.com/pyenv/pyenv-virtualenv/pull/330
* fix: relative path to pyenv-realpath.dylib by @scop in https://github.com/pyenv/pyenv-virtualenv/pull/378
* Spelling fixes by @scop in https://github.com/pyenv/pyenv-virtualenv/pull/352
* Clone bats with --depth=1, gitignore it by @scop in https://github.com/pyenv/pyenv-virtualenv/pull/351
* set -u fixes by @scop in https://github.com/pyenv/pyenv-virtualenv/pull/350
* Set up Github Actions CI by @native-api in https://github.com/pyenv/pyenv-virtualenv/pull/440
* Enhance documentation about options for `pyenv virtualenv` by @pylipp in https://github.com/pyenv/pyenv-virtualenv/pull/425
* Return control to pyenv-uninstall in uninstall/envs.bash by @aiguofer in https://github.com/pyenv/pyenv-virtualenv/pull/321
* Use realpath of scripts to determine relative locations by @andrew-christianson in https://github.com/pyenv/pyenv-virtualenv/pull/308
* Shell detect improvements by @scop in https://github.com/pyenv/pyenv-virtualenv/pull/377
## v1.1.5
* Fix install script (#290, #302) * Fix install script (#290, #302)
#### 1.1.4 ## v1.1.4
* Support newer conda (#290) * Support newer conda (#290)
* Prefer `python3.x` executable if available (#206, #282, #296) * Prefer `python3.x` executable if available (#206, #282, #296)
#### 1.1.3 ## v1.1.3
* No code changes since 1.1.2 * No code changes since 1.1.2
#### 1.1.2 ## v1.1.2
* Use custom get-pip URL based on the target version (#253, #254, #255) * Use custom get-pip URL based on the target version (#253, #254, #255)
* Source conda 4.4.4 shell files (#251) * Source conda 4.4.4 shell files (#251)
* Evaluate force flag before testing if venv exists (#232) * Evaluate force flag before testing if venv exists (#232)
#### 1.1.1 ## v1.1.1
* Set `CONDA_PREFIX` to make is useable in conda activate/deactivate scripts (#224) * Set `CONDA_PREFIX` to make is useable in conda activate/deactivate scripts (#224)
* Generate `pydoc` executable after creating new virtualenv (#197, #230) * Generate `pydoc` executable after creating new virtualenv (#197, #230)
#### 1.1.0 ## v1.1.0
* fish: use "set -gx" instead of "setenv" (#215, #216, #217, #218) * fish: use "set -gx" instead of "setenv" (#215, #216, #217, #218)
#### 1.0.0 ## v1.0.0
* Use similar versioning scheme as pyenv; YYYYMMDD -> X.Y.Z * Use similar versioning scheme as pyenv; YYYYMMDD -> X.Y.Z
#### 20160716 ## v20160716
* Suppress activate/deactivate messages by default (#169, #170, #171) * Suppress activate/deactivate messages by default (#169, #170, #171)
* Source conda package activate/deactivat scripts if exist (#173) * Source conda package activate/deactivat scripts if exist (#173)
* Use `source` in favor of `.` for `fish` (#175) * Use `source` in favor of `.` for `fish` (#175)
* Use `python -m venv` instead of `pyvenv` due to deprecation of `pyvenv` after 3.6 (#184, #185) * Use `python -m venv` instead of `pyvenv` due to deprecation of `pyvenv` after 3.6 (#184, #185)
#### 20160315 ## v20160315
* Evaluate `${PATH}` when outputted code is eval'd. (#154) * Evaluate `${PATH}` when outputted code is eval'd. (#154)
* Set proper `CONDA_DEFAULT_ENV` for shorter name (#160) * Set proper `CONDA_DEFAULT_ENV` for shorter name (#160)
#### 20160202 ## v20160202
* Install virtualenv 13.1.2 for CPython/Stackless 3.2.x (yyuu/pyenv#531) * Install virtualenv 13.1.2 for CPython/Stackless 3.2.x (yyuu/pyenv#531)
#### 20160112 ## v20160112
* Fix problem with `virtualenv` to look up executables from source version with `--system-site-packages` (#62) * Fix problem with `virtualenv` to look up executables from source version with `--system-site-packages` (#62)
#### 20151229 ## v20151229
* Fix `deactivate` error on `fish` (#136) * Fix `deactivate` error on `fish` (#136)
#### 20151222 ## v20151222
* Improved interoperability with Anaconda/Miniconda (#103, #106, #107, #108) * Improved interoperability with Anaconda/Miniconda (#103, #106, #107, #108)
* Create `virtualenv` inside `envs` directory of source version, like Anaconda/Miniconda (#103, #107) * Create `virtualenv` inside `envs` directory of source version, like Anaconda/Miniconda (#103, #107)
@ -66,49 +135,49 @@
* Add `--skip-aliases` to `pyenv virtualenvs` (#120) * Add `--skip-aliases` to `pyenv virtualenvs` (#120)
* Stop showing `version not installed` warning messages in precmd (#49) * Stop showing `version not installed` warning messages in precmd (#49)
#### 20151103 ## v20151103
* Passing return value from executed command. (#100) * Passing return value from executed command. (#100)
* Add workaround for commands installed in a virtual environment created by `pyvenv` (#62) * Add workaround for commands installed in a virtual environment created by `pyvenv` (#62)
* init: zsh: prepend hook to `precmd_functions` (#101) * init: zsh: prepend hook to `precmd_functions` (#101)
#### 20151006 ## v20151006
* Ignore user's site-packages on ensurepip/get-pip (#89) * Ignore user's site-packages on ensurepip/get-pip (#89)
* Find `python-config` from source version if current version is a virtualenv * Find `python-config` from source version if current version is a virtualenv
* Fix pyenv-virtualenv-init script for fish where command was in string and not being evaluated (#98) * Fix pyenv-virtualenv-init script for fish where command was in string and not being evaluated (#98)
* Add foolproof for `-p` argument. (yyuu/pyenv#98) * Add foolproof for `-p` argument. (yyuu/pyenv#98)
#### 20150719 ## v20150719
* Add support for `conda` environments created by Anaconda/Miniconda (#91) * Add support for `conda` environments created by Anaconda/Miniconda (#91)
* Look up commands for original version as well if the environment is created with `--system-site-packages` (#62) * Look up commands for original version as well if the environment is created with `--system-site-packages` (#62)
* Add error message if the source version is not installed (#83) * Add error message if the source version is not installed (#83)
#### 20150526 ## v20150526
* Use `typeset -g` with `precmd_functions` (#75) * Use `typeset -g` with `precmd_functions` (#75)
* activate: display setup instructions only with `PYENV_VIRTUALENV_INIT=0` (#78) * activate: display setup instructions only with `PYENV_VIRTUALENV_INIT=0` (#78)
* Ignore failure of pyenv activate (#68) * Ignore failure of pyenv activate (#68)
#### 20150119 ## v20150119
* Ignore errors from `pyenv-version-name` since it might fail if there is configuration error (yyuu/pyenv#291) * Ignore errors from `pyenv-version-name` since it might fail if there is configuration error (yyuu/pyenv#291)
* The _shell_ version set in `activate` should be unset in `deactivate` (#61) * The _shell_ version set in `activate` should be unset in `deactivate` (#61)
* Anaconda has `activate` script nevertheless it is not a virtual environment (#65) * Anaconda has `activate` script nevertheless it is not a virtual environment (#65)
#### 20141106 ## v20141106
* Stop creating after `ensurepip` since it has done by `ensurepip` itself * Stop creating after `ensurepip` since it has done by `ensurepip` itself
* Suppress some useless warnings from `pyenv virtualenv-init` * Suppress some useless warnings from `pyenv virtualenv-init`
#### 20141012 ## v20141012
* Fix warnings from `shellcheck` to improve support for POSIX sh (#40) * Fix warnings from `shellcheck` to improve support for POSIX sh (#40)
* Do not allow whitespace in `VIRTUALENV_NAME` (#44) * Do not allow whitespace in `VIRTUALENV_NAME` (#44)
* Should not persist `PYENV_DEACTIVATE` after automatic deactivation (#47, #48) * Should not persist `PYENV_DEACTIVATE` after automatic deactivation (#47, #48)
#### 20140705 ## v20140705
* Display information on auto-(de)?activation * Display information on auto-(de)?activation
* Support manual (de)?activation with auto-activation enabled (#32, #34) * Support manual (de)?activation with auto-activation enabled (#32, #34)
@ -116,88 +185,88 @@
* Use https://bootstrap.pypa.io/ to install setuptools and pip * Use https://bootstrap.pypa.io/ to install setuptools and pip
* Create backup of original virtualenv within `$(pyenv root)/versions` when `--upgrade` * Create backup of original virtualenv within `$(pyenv root)/versions` when `--upgrade`
#### 20140615 ## v20140615
* Fix incompatibility issue of `pyenv activate` and `pyenv deactivate` (#26) * Fix incompatibility issue of `pyenv activate` and `pyenv deactivate` (#26)
* Workaround for the issue with pyenv-which-ext (#26) * Workaround for the issue with pyenv-which-ext (#26)
#### 20140614 ## v20140614
* Add `pyenv virtualenv-init` to enable auto-activation feature (#24) * Add `pyenv virtualenv-init` to enable auto-activation feature (#24)
* Create symlinks for executables with version suffix (yyuu/pyenv#182) * Create symlinks for executables with version suffix (yyuu/pyenv#182)
#### 20140602 ## v20140602
* Use new style GH raw url to avoid redirects (raw.github.com -> raw.githubusercontent.com) * Use new style GH raw url to avoid redirects (raw.github.com -> raw.githubusercontent.com)
* Repaired virtualenv activation and deactivation for the fish shell (#23) * Repaired virtualenv activation and deactivation for the fish shell (#23)
#### 20140421 ## v20140421
* Display error if `pyenv activate` was invoked as a command * Display error if `pyenv activate` was invoked as a command
* Fix completion of `pyenv activate` (#15) * Fix completion of `pyenv activate` (#15)
* Use `virtualenv` instead of `pyvenv` if `-p` has given (yyuu/pyenv#158) * Use `virtualenv` instead of `pyvenv` if `-p` has given (yyuu/pyenv#158)
#### 20140123 ## v20140123
* Add `activate` and `deactivate` to make `pyenv-virtualenv` work with [jedi](https://github.com/davidhalter/jedi) (#9) * Add `activate` and `deactivate` to make `pyenv-virtualenv` work with [jedi](https://github.com/davidhalter/jedi) (#9)
* Use `ensurepip` to install `pip` if it is available * Use `ensurepip` to install `pip` if it is available
* Unset `PIP_REQUIRE_VENV` to avoid problem on the installation of `virtualenv` (#10) * Unset `PIP_REQUIRE_VENV` to avoid problem on the installation of `virtualenv` (#10)
* Add tests * Add tests
#### 20140110.1 ## v20140110.1
* Fix install script * Fix install script
#### 20140110 ## v20140110
* Support environment variables of `EZ_SETUP` and `GET_PIP`. * Support environment variables of `EZ_SETUP` and `GET_PIP`.
* Support a short option `-p` of `virtualenv`. * Support a short option `-p` of `virtualenv`.
#### 20131216 ## v20131216
* Use latest release of setuptools and pip if the version not given via environment variables. * Use latest release of setuptools and pip if the version not given via environment variables.
#### 20130622 ## v20130622
* Removed bundled `virtualenv.py` script. Now pyenv-virtualenv installs `virtualenv` package into source version and then use it. * Removed bundled `virtualenv.py` script. Now pyenv-virtualenv installs `virtualenv` package into source version and then use it.
* On Python 3.3+, use `pyvenv` as virtualenv command if `virtualenv` is not available. * On Python 3.3+, use `pyvenv` as virtualenv command if `virtualenv` is not available.
* Install setuptools and pip into environments created by `pyvenv`. * Install setuptools and pip into environments created by `pyvenv`.
#### 20130614 ## v20130614
* Add `pyenv virtualenvs` to list all virtualenv versions. * Add `pyenv virtualenvs` to list all virtualenv versions.
* *EXPERIMENTAL*: Add `--upgrade` option to re-create virtualenv with migrating packages * *EXPERIMENTAL*: Add `--upgrade` option to re-create virtualenv with migrating packages
#### 20130527 ## v20130527
* Remove `python-virtualenv` which was no longer used. * Remove `python-virtualenv` which was no longer used.
* Change the installation path of the `virtualenv.py` script. (`./libexec` -> `./libexec/pyenv-virtualenv/${VIRTUALENV_VERSION}`) * Change the installation path of the `virtualenv.py` script. (`./libexec` -> `./libexec/pyenv-virtualenv/${VIRTUALENV_VERSION}`)
* Download `virtualenv.py` if desired version has not been installed. * Download `virtualenv.py` if desired version has not been installed.
#### 20130507 ## v20130507
* Display virtualenv information in `--help` and `--version` * Display virtualenv information in `--help` and `--version`
* Update virtualenv version; 1.8.4 -> 1.9.1 * Update virtualenv version; 1.8.4 -> 1.9.1
#### 20130307 ## v20130307
* Rename the project; `s/python-virtualenv/pyenv-virtualenv/g` * Rename the project; `s/python-virtualenv/pyenv-virtualenv/g`
* The `pyenv-virtualenv` script is not depending on `python-virtualenv` now. * The `pyenv-virtualenv` script is not depending on `python-virtualenv` now.
`python-virtualenv` will left for compatibility and will not continue for future releases. `python-virtualenv` will left for compatibility and will not continue for future releases.
* Update virtualenv version; 1.8.2 -> 1.8.4 * Update virtualenv version; 1.8.2 -> 1.8.4
#### 20130218 ## v20130218
* Add pyenv 0.2.x (rbenv 0.4.x) style help messages. * Add pyenv 0.2.x (rbenv 0.4.x) style help messages.
#### 20121023 ## v20121023
* Create virtualenv with exact name of python executables. * Create virtualenv with exact name of python executables.
* Changed command-line options of python-virtualenv. * Changed command-line options of python-virtualenv.
First argument should be a path to the python executable. First argument should be a path to the python executable.
* Add install script. * Add install script.
#### 20120927 ## v20120927
* Initial public release. * Initial public release.

View file

@ -1,4 +1,4 @@
Copyright (c) 2015 Yamashita, Yuu Copyright (c) 2025 Yamashita, Yuu
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

15
MAINTENANCE.md Normal file
View file

@ -0,0 +1,15 @@
Creating a release
==================
The release of the new version of Pyenv is done via GitHub Releases.
Release checklist:
* Start [drafting a new release on GitHub](https://github.com/pyenv/pyenv-virtualenv/releases) to generate a summary of changes. Save the summary locally.
* The summary may need editing. E.g. rephrase entries, delete/merge entries that are too minor or irrelevant to the users (e.g. typo fixes, CI)
* Push the version number in `bin/pyenv-virtualenv`
* Minor version is pushed if there are significant functional changes (not e.g. bugfixes/formula adaptations/supporting niche use cases).
* Major version is pushed if there are breaking changes
* Update `CHANGELOG.md` with the new version number and the edited summary (only the changes section), reformatting it like the rest of the changelog sections
* Commit the changes locally into `master`
* Create a new tag with the new version number and push the changes including the tag
* Create a new release on GitHub based on the tag, using the saved summary

View file

@ -28,21 +28,33 @@ From inside that directory you can:
- Get the latest development release by running `git pull` to download the - Get the latest development release by running `git pull` to download the
latest changes. latest changes.
💡 **WSL note:** If you're using WSL, we recommend setting Git to use Unix-style line endings to prevent script execution errors:
```sh
git config --global core.autocrlf input
```
1. **Check out pyenv-virtualenv into plugin directory** 1. **Check out pyenv-virtualenv into plugin directory**
```sh ```bash
$ git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv
```
For the Fish shell:
```fish
git clone https://github.com/pyenv/pyenv-virtualenv.git (pyenv root)/plugins/pyenv-virtualenv
``` ```
2. (OPTIONAL) **Add `pyenv virtualenv-init` to your shell** to enable auto-activation of virtualenvs. This is entirely optional but pretty useful. See "Activate virtualenv" below. 2. (OPTIONAL) **Add `pyenv virtualenv-init` to your shell** to enable auto-activation of virtualenvs. This is entirely optional but pretty useful. See "Activate virtualenv" below.
```sh ```bash
$ echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
``` ```
**Fish shell note**: Add this to your `~/.config/fish/config.fish` **Fish shell note**: Add this to your `~/.config/fish/config.fish`
```sh ```fish
status --is-interactive; and pyenv virtualenv-init - | source status --is-interactive; and pyenv virtualenv-init - | source
``` ```
@ -50,8 +62,8 @@ From inside that directory you can:
3. **Restart your shell to enable pyenv-virtualenv** 3. **Restart your shell to enable pyenv-virtualenv**
```sh ```bash
$ exec "$SHELL" exec "$SHELL"
``` ```
@ -66,17 +78,17 @@ installed, you will also be able to use the `pyenv virtualenv` command.
with Homebrew.* with Homebrew.*
```sh ```sh
$ brew install pyenv-virtualenv brew install pyenv-virtualenv
``` ```
Or, if you would like to install the latest development release: Or, if you would like to install the latest development release:
```sh ```sh
$ brew install --HEAD pyenv-virtualenv brew install --HEAD pyenv-virtualenv
``` ```
After installation, you'll still need to do After installation, you'll still need to do
[Pyenv shell setup steps](https://github.com/pyenv/pyenv#basic-github-checkout) [Pyenv shell setup steps](https://github.com/pyenv/pyenv#b-set-up-your-shell-environment-for-pyenv)
then add then add
```sh ```sh
eval "$(pyenv virtualenv-init -)" eval "$(pyenv virtualenv-init -)"
@ -93,7 +105,7 @@ To create a virtualenv for the Python version used with pyenv, run
of the virtualenv directory. For example, of the virtualenv directory. For example,
```sh ```sh
$ pyenv virtualenv 2.7.10 my-virtual-env-2.7.10 pyenv virtualenv 2.7.10 my-virtual-env-2.7.10
``` ```
will create a virtualenv based on Python 2.7.10 under `$(pyenv root)/versions` in a will create a virtualenv based on Python 2.7.10 under `$(pyenv root)/versions` in a
@ -237,6 +249,7 @@ You can set certain environment variables to control pyenv-virtualenv.
* `PIP_VERSION`, if set and `venv` is preferred * `PIP_VERSION`, if set and `venv` is preferred
over `virtualenv`, install the specified version of pip. over `virtualenv`, install the specified version of pip.
* `PYENV_VIRTUALENV_VERBOSE_ACTIVATE`, if set, shows some verbose outputs on activation and deactivation * `PYENV_VIRTUALENV_VERBOSE_ACTIVATE`, if set, shows some verbose outputs on activation and deactivation
* `PYENV_VIRTUALENV_PROMPT`, if set, allows users to customize how `pyenv-virtualenv` modifies their shell prompt. The default prompt ("(venv)") is overwritten with any user-specified text. Specify the location of the virtual environment name with the string `{venv}`. For example, the default prompt string would be `({venv})`.
## Version History ## Version History

View file

@ -22,10 +22,8 @@ fi
{ printf "\x1B[31;1m" { printf "\x1B[31;1m"
echo echo
echo "Failed to activate virtualenv." echo "\`pyenv activate' requires Pyenv and Pyenv-Virtualenv to be loaded into your shell."
echo echo "Check your shell configuration and Pyenv and Pyenv-Virtualenv installation instructions."
echo "Perhaps pyenv-virtualenv has not been loaded into your shell properly."
echo "Please restart current shell and try again."
echo echo
printf "\x1B[0m" printf "\x1B[0m"
} 1>&2 } 1>&2

View file

@ -11,10 +11,8 @@ set -e
{ printf "\x1B[31;1m" { printf "\x1B[31;1m"
echo echo
echo "Failed to deactivate virtualenv." echo "\`pyenv deactivate' requires Pyenv and Pyenv-Virtualenv to be loaded into your shell."
echo echo "Check your shell configuration and Pyenv and Pyenv-Virtualenv installation instructions."
echo "Perhaps pyenv-virtualenv has not been loaded into your shell properly."
echo "Please restart current shell and try again."
echo echo
printf "\x1B[0m" printf "\x1B[0m"
} 1>&2 } 1>&2

View file

@ -25,6 +25,27 @@ resolve_link() {
unset FORCE unset FORCE
unset QUIET unset QUIET
# Define `before_activate` and `after_activate` functions that allow
# plugin hooks to register a string of code for execution before or
# after activating a virtualenv.
declare -a before_hooks after_hooks
before_activate() {
local hook="$1"
before_hooks["${#before_hooks[@]}"]="$hook"
}
after_activate() {
local hook="$1"
after_hooks["${#after_hooks[@]}"]="$hook"
}
# Load plugin hooks.
OLDIFS="$IFS"
IFS=$'\n' scripts=(`pyenv-hooks activate`)
IFS="$OLDIFS"
for script in "${scripts[@]}"; do source "$script"; done
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
"--complete" ) "--complete" )
@ -75,8 +96,8 @@ fi
venv="${versions}" venv="${versions}"
if [ -n "${VIRTUAL_ENV}" ]; then if [ -n "${VIRTUAL_ENV}" ]; then
# exit as success if some virtualenv is already activated outside from pyenv-virtualenv # exit as success if a non-pyenv virtualenv is active
if [ -z "${PYENV_VIRTUAL_ENV}" ]; then if [[ -z $PYENV_VIRTUAL_ENV || $PYENV_VIRTUAL_ENV != "$VIRTUAL_ENV" ]]; then
if [ -z "${FORCE}" ]; then if [ -z "${FORCE}" ]; then
if [ -z "${QUIET}" ]; then if [ -z "${QUIET}" ]; then
echo "pyenv-virtualenv: virtualenv \`${VIRTUAL_ENV}' is already activated" 1>&2 echo "pyenv-virtualenv: virtualenv \`${VIRTUAL_ENV}' is already activated" 1>&2
@ -137,6 +158,9 @@ fi
pyenv-sh-deactivate --force --quiet || true pyenv-sh-deactivate --force --quiet || true
# Execute `before_activate` hooks.
for hook in "${before_hooks[@]}"; do eval "$hook"; done
if [ -n "$PYENV_VIRTUALENV_VERBOSE_ACTIVATE" ]; then if [ -n "$PYENV_VIRTUALENV_VERBOSE_ACTIVATE" ]; then
echo "pyenv-virtualenv: activate ${venv}" 1>&2 echo "pyenv-virtualenv: activate ${venv}" 1>&2
fi fi
@ -221,16 +245,31 @@ if [ -z "${PYENV_VIRTUALENV_DISABLE_PROMPT}" ]; then
case "${shell}" in case "${shell}" in
fish ) fish )
if [ -z "${QUIET}" ]; then if [ -z "${QUIET}" ]; then
echo "pyenv-virtualenv: prompt changing not working for fish." 1>&2 cat <<EOS
functions -e _pyenv_old_prompt # remove old prompt function if exists.
# since everything is in memory, it's safe to
# remove it.
functions -c fish_prompt _pyenv_old_prompt # backup old prompt function
# from python-venv
function fish_prompt
set -l prompt (_pyenv_old_prompt) # call old prompt function first since it might
# read exit status
echo -n "(${venv}) " # add virtualenv to prompt
string join -- \n \$prompt # handle multiline prompts
end
EOS
fi fi
;; ;;
* ) * )
if [ -z "${QUIET}" ]; then if [ -z "${PYENV_VIRTUALENV_PROMPT}" ]; then
echo "pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior." 1>&2 PYENV_VIRTUALENV_PROMPT="(${venv})"
else
PYENV_VIRTUALENV_PROMPT="${PYENV_VIRTUALENV_PROMPT/\{venv\}/${venv}}"
fi fi
cat <<EOS cat <<EOS
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(${venv}) \${PS1:-}"; export PS1="${PYENV_VIRTUALENV_PROMPT} \${PS1:-}";
EOS EOS
;; ;;
esac esac
@ -261,3 +300,6 @@ if [ -d "${prefix}/conda-meta" ] ||
esac esac
shopt -u nullglob shopt -u nullglob
fi fi
# Execute `after_activate` hooks.
for hook in "${after_hooks[@]}"; do eval "$hook"; done

View file

@ -16,6 +16,27 @@ fi
unset FORCE unset FORCE
unset QUIET unset QUIET
# Define `before_deactivate` and `after_deactivate` functions that allow
# plugin hooks to register a string of code for execution before or
# after deactivating a virtualenv.
declare -a before_hooks after_hooks
before_deactivate() {
local hook="$1"
before_hooks["${#before_hooks[@]}"]="$hook"
}
after_deactivate() {
local hook="$1"
after_hooks["${#after_hooks[@]}"]="$hook"
}
# Load plugin hooks.
OLDIFS="$IFS"
IFS=$'\n' scripts=(`pyenv-hooks deactivate`)
IFS="$OLDIFS"
for script in "${scripts[@]}"; do source "$script"; done
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
"-f" | "--force" ) "-f" | "--force" )
@ -54,6 +75,9 @@ else
venv="${prefix##*/}" venv="${prefix##*/}"
fi fi
# Execute `before_deactivate` hooks.
for hook in "${before_hooks[@]}"; do eval "$hook"; done
if [ -n "$PYENV_VIRTUALENV_VERBOSE_ACTIVATE" ]; then if [ -n "$PYENV_VIRTUALENV_VERBOSE_ACTIVATE" ]; then
echo "pyenv-virtualenv: deactivate ${venv}" 1>&2 echo "pyenv-virtualenv: deactivate ${venv}" 1>&2
fi fi
@ -163,7 +187,15 @@ esac
case "${shell}" in case "${shell}" in
fish ) fish )
: cat <<EOS
# check if old prompt function exists
if functions -q _pyenv_old_prompt
# remove old prompt function if exists.
functions -e fish_prompt
functions -c _pyenv_old_prompt fish_prompt
functions -e _pyenv_old_prompt
end
EOS
;; ;;
* ) * )
cat <<EOS cat <<EOS
@ -191,3 +223,6 @@ fi;
EOS EOS
;; ;;
esac esac
# Execute `after_deactivate` hooks.
for hook in "${after_hooks[@]}"; do eval "$hook"; done

View file

@ -13,7 +13,7 @@
# -u/--upgrade Imply --force # -u/--upgrade Imply --force
# #
PYENV_VIRTUALENV_VERSION="1.1.5" PYENV_VIRTUALENV_VERSION="1.4.0"
set -e set -e
[ -n "$PYENV_DEBUG" ] && set -x [ -n "$PYENV_DEBUG" ] && set -x
@ -24,7 +24,7 @@ fi
# Provide pyenv completions # Provide pyenv completions
if [ "$1" = "--complete" ]; then if [ "$1" = "--complete" ]; then
exec pyenv-versions --bare exec pyenv-versions --bare --skip-envs
fi fi
unset PIP_REQUIRE_VENV unset PIP_REQUIRE_VENV
@ -54,6 +54,12 @@ parse_options() {
done done
} }
colorize() {
if [ -t 1 ]; then printf "\e[%sm%s\e[m" "$1" "$2"
else echo -n "$2"
fi
}
resolve_link() { resolve_link() {
$(type -p greadlink readlink | head -1) "$1" $(type -p greadlink readlink | head -1) "$1"
} }
@ -149,9 +155,17 @@ detect_venv() {
if [ -x "${prefix}/bin/virtualenv" ]; then if [ -x "${prefix}/bin/virtualenv" ]; then
HAS_VIRTUALENV=1 HAS_VIRTUALENV=1
fi fi
# Prefer `python3.x` executable if available (#206, #282)
local python local python
for python in "python${PYENV_VERSION%.*}" "python${PYENV_VERSION%%.*}" "python"; do local -a pythons
if [[ $PYENV_VERSION == "system" ]]; then
# Prefer `python3.x` executable if available (#206, #282)
pythons=("python3" "python" "python2")
else
# as per PEP 394, custom activated Python environments should provide the "python" command
# this includes Pyenv-provided installations
pythons=("python")
fi
for python in "${pythons[@]}"; do
if pyenv-exec "${python}" -m venv --help 1>/dev/null 2>&1; then if pyenv-exec "${python}" -m venv --help 1>/dev/null 2>&1; then
HAS_M_VENV=1 HAS_M_VENV=1
M_VENV_PYTHON_BIN="${python}" M_VENV_PYTHON_BIN="${python}"
@ -311,7 +325,7 @@ else
fi fi
if [[ -n "${VERSION_NAME}" ]] && command -v pyenv-latest >/dev/null; then if [[ -n "${VERSION_NAME}" ]] && command -v pyenv-latest >/dev/null; then
VERSION_NAME="$(pyenv-latest -q "${VERSION_NAME}" || echo "${VERSION_NAME}")" VERSION_NAME="$(pyenv-latest -f "${VERSION_NAME}")"
fi fi
if [ -z "${VERSION_NAME}" ] || [ -z "${VIRTUALENV_NAME}" ]; then if [ -z "${VERSION_NAME}" ] || [ -z "${VIRTUALENV_NAME}" ]; then
@ -336,10 +350,20 @@ fi
# Set VERSION_NAME as default version in this script # Set VERSION_NAME as default version in this script
export PYENV_VERSION="${VERSION_NAME}" export PYENV_VERSION="${VERSION_NAME}"
not_installed_message() {
local is_available=$(python-build --definitions | grep -F -x "$1")
echo "pyenv-virtualenv: \`${1}' is not installed in pyenv." 1>&2
if [[ $is_available ]]; then
echo "Run \`pyenv install ${1}' to install it." 1>&2
else
echo "It does not look like a valid Python version. See \`pyenv install --list' for available versions." 1>&2
fi
}
# Source version must exist before creating virtualenv. # Source version must exist before creating virtualenv.
PREFIX="$(pyenv-prefix 2>/dev/null || true)" PREFIX="$(pyenv-prefix 2>/dev/null || true)"
if [ ! -d "${PREFIX}" ]; then if [ ! -d "${PREFIX}" ]; then
echo "pyenv-virtualenv: \`${PYENV_VERSION}' is not installed in pyenv." 1>&2 not_installed_message "${PYENV_VERSION}"
exit 1 exit 1
fi fi
@ -441,7 +465,8 @@ else
if [ -x "${python}" ]; then if [ -x "${python}" ]; then
VIRTUALENV_OPTIONS[${#VIRTUALENV_OPTIONS[*]}]="--python=${python}" VIRTUALENV_OPTIONS[${#VIRTUALENV_OPTIONS[*]}]="--python=${python}"
else else
echo "pyenv-virtualenv: \`${VIRTUALENV_PYTHON##*/}' is not installed in pyenv." 1>&2 # echo "pyenv-virtualenv: \`${VIRTUALENV_PYTHON##*/}' is not installed in pyenv." 1>&2
not_installed_message "${VIRTUALENV_PYTHON##*/}"
exit 1 exit 1
fi fi
fi fi
@ -580,7 +605,13 @@ STATUS=0
mkdir -p "${PYENV_VIRTUALENV_CACHE_PATH}" mkdir -p "${PYENV_VIRTUALENV_CACHE_PATH}"
cd "${PYENV_VIRTUALENV_CACHE_PATH}" cd "${PYENV_VIRTUALENV_CACHE_PATH}"
if [ -n "${USE_CONDA}" ]; then if [ -n "${USE_CONDA}" ]; then
pyenv-exec conda create $QUIET $VERBOSE --name "${VIRTUALENV_PATH##*/}" --yes "${VIRTUALENV_OPTIONS[@]}" python || STATUS="$?" if [ -z "$VIRTUALENV_PYTHON" ]; then
#process substitution doesn't seem to work unless it's directly inserted to the command line
#if we add it to VIRTUALENV_OPTIONS instead, "broken pipe" happens
pyenv-exec conda create $QUIET $VERBOSE --name "${VIRTUALENV_PATH##*/}" --yes "${VIRTUALENV_OPTIONS[@]}" --file <(pyenv-exec conda list python --full-name --export) || STATUS="$?"
else
pyenv-exec conda create $QUIET $VERBOSE --name "${VIRTUALENV_PATH##*/}" --yes "${VIRTUALENV_OPTIONS[@]}" || STATUS="$?"
fi
else else
if [ -n "${USE_M_VENV}" ]; then if [ -n "${USE_M_VENV}" ]; then
pyenv-exec "${M_VENV_PYTHON_BIN:-python}" -m venv $QUIET $VERBOSE "${VIRTUALENV_OPTIONS[@]}" "${VIRTUALENV_PATH}" || STATUS="$?" pyenv-exec "${M_VENV_PYTHON_BIN:-python}" -m venv $QUIET $VERBOSE "${VIRTUALENV_OPTIONS[@]}" "${VIRTUALENV_PATH}" || STATUS="$?"
@ -589,9 +620,19 @@ else
fi fi
fi fi
(
shopt -s nullglob
for extra_binary in "$PREFIX"/bin/python*-config; do
extra_binary_linkname="$VIRTUALENV_PATH/bin/$(basename $extra_binary)"
[[ -e "$extra_binary_linkname" ]] || \
ln -s "$extra_binary" "$extra_binary_linkname"
done
)
## Create symlink in the `versions` directory for backward compatibility ## Create symlink in the `versions` directory for backward compatibility
if [ -d "${VIRTUALENV_PATH}" ] && [ -n "${COMPAT_VIRTUALENV_PATH}" ]; then if [ -d "${VIRTUALENV_PATH}" ] && [ -n "${COMPAT_VIRTUALENV_PATH}" ]; then
ln -fs "${VIRTUALENV_PATH}" "${COMPAT_VIRTUALENV_PATH}" # Overwrite an existing link, can happen if running with -f
ln -fsn "${VIRTUALENV_PATH}" "${COMPAT_VIRTUALENV_PATH}"
fi fi
if [ ! -e "${VIRTUALENV_PATH}/bin/pydoc" ]; then if [ ! -e "${VIRTUALENV_PATH}/bin/pydoc" ]; then

View file

@ -55,26 +55,28 @@ case "$DEFINITION" in
esac esac
VERSION_NAME="${DEFINITION##*/}" VERSION_NAME="${DEFINITION##*/}"
COMPAT_PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}" # Must initialize because it might be set in the environment
ENV_PREFIX=
ENV_COMPAT_PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
if [[ "${DEFINITION}" != "${DEFINITION%/envs/*}" ]]; then if [[ "${DEFINITION}" != "${DEFINITION%/envs/*}" ]]; then
PREFIX="${PYENV_ROOT}/versions/${DEFINITION}" ENV_PREFIX="${PYENV_ROOT}/versions/${DEFINITION}"
if [ -L "${COMPAT_PREFIX}" ]; then if [ -L "${ENV_COMPAT_PREFIX}" ]; then
if [[ "${PREFIX}" != "$(resolve_link "${COMPAT_PREFIX}" 2>/dev/null || true)" ]]; then if [[ "${ENV_PREFIX}" != "$(resolve_link "${ENV_COMPAT_PREFIX}" 2>/dev/null || true)" ]]; then
unset COMPAT_PREFIX unset ENV_COMPAT_PREFIX
fi fi
fi fi
else else
if [ -L "${COMPAT_PREFIX}" ]; then if [ -L "${ENV_COMPAT_PREFIX}" ]; then
PREFIX="$(resolve_link "${COMPAT_PREFIX}" 2>/dev/null || true)" ENV_PREFIX="$(resolve_link "${ENV_COMPAT_PREFIX}" 2>/dev/null || true)"
if [[ "${PREFIX%/*/envs/*}" != "${PYENV_ROOT}/versions" ]]; then if [[ "${ENV_PREFIX%/*/envs/*}" != "${PYENV_ROOT}/versions" ]]; then
echo "pyenv-virtualenv: \`${COMPAT_PREFIX}' is a symlink for unknown location." 1>&2 echo "pyenv-virtualenv: \`${ENV_COMPAT_PREFIX}' is a symlink for unknown location." 1>&2
exit 1 exit 1
fi fi
else else
if pyenv-virtualenv-prefix "${VERSION_NAME}" 1>/dev/null 2>&1; then if pyenv-virtualenv-prefix "${VERSION_NAME}" 1>/dev/null 2>&1; then
PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}" ENV_PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
unset COMPAT_PREFIX unset ENV_COMPAT_PREFIX
elif [ -z "$FORCE" ]; then elif [ -z "$FORCE" ]; then
echo "pyenv-virtualenv: \`${DEFINITION}' is not a virtualenv." 1>&2 echo "pyenv-virtualenv: \`${DEFINITION}' is not a virtualenv." 1>&2
exit 1 exit 1
@ -82,23 +84,25 @@ else
fi fi
fi fi
if [ -z "$FORCE" ]; then if [ ! -d "$ENV_PREFIX" ]; then
if [ ! -d "$PREFIX" ]; then if [ -z "$FORCE" ]; then
echo "pyenv-virtualenv: virtualenv \`$VERSION_NAME' not installed" >&2 echo "pyenv-virtualenv: virtualenv \`$VERSION_NAME' not installed" >&2
exit 1 exit 1
else
exit 0
fi fi
fi
read -p "pyenv-virtualenv: remove $PREFIX? (y/N) " if [ -z "$FORCE" ]; then
read -p "pyenv-virtualenv: remove $ENV_PREFIX? (y/N) "
case "$REPLY" in case "$REPLY" in
y* | Y* ) ;; y* | Y* ) ;;
* ) exit 1 ;; * ) exit 1 ;;
esac esac
fi fi
if [ -d "$PREFIX" ]; then rm -rf "$ENV_PREFIX"
rm -rf "$PREFIX" if [ -L "$ENV_COMPAT_PREFIX" ]; then
if [ -L "$COMPAT_PREFIX" ]; then rm -rf "$ENV_COMPAT_PREFIX"
rm -rf "$COMPAT_PREFIX"
fi
pyenv-rehash
fi fi
pyenv-rehash

View file

@ -9,6 +9,23 @@
set -e set -e
[ -n "$PYENV_DEBUG" ] && set -x [ -n "$PYENV_DEBUG" ] && set -x
# Detect stat format for mtime: GNU uses -c %Y, BSD uses -f %m
# -L follows symlinks: a symlinked .python-version reflects target changes
if stat -L -c %Y / >/dev/null 2>&1; then
_stat_fmt="-L -c %Y"
else
_stat_fmt="-L -f %m"
fi
# Check for version-name hooks at init time. Hooks can alter version
# resolution in ways the mtime cache cannot track. If present, the hook
# falls back to upstream behavior (no caching). Restart shell after
# installing or removing pyenv plugins.
_has_version_hooks=""
if [ -n "$(pyenv hooks version-name 2>/dev/null)" ]; then
_has_version_hooks=1
fi
resolve_link() { resolve_link() {
$(type -p greadlink readlink | head -1) "$1" $(type -p greadlink readlink | head -1) "$1"
} }
@ -106,57 +123,147 @@ fish )
cat <<EOS cat <<EOS
function _pyenv_virtualenv_hook --on-event fish_prompt; function _pyenv_virtualenv_hook --on-event fish_prompt;
set -l ret \$status set -l ret \$status
EOS
if [ -z "$_has_version_hooks" ]; then
cat <<EOS
if test "\$PYENV_VERSION" = "\$_PYENV_VH_VERSION" \\
-a "\$VIRTUAL_ENV" = "\$_PYENV_VH_VENV"
if test -n "\$PYENV_VERSION"
return \$ret
end
if test "\$PWD" = "\$_PYENV_VH_PWD" \\
-a "(stat ${_stat_fmt} \$_PYENV_VH_PATHS 2>/dev/null)" = "\$_PYENV_VH_MTIMES"
return \$ret
end
end
EOS
fi
cat <<EOS
if [ -n "\$VIRTUAL_ENV" ] if [ -n "\$VIRTUAL_ENV" ]
pyenv activate --quiet; or pyenv deactivate --quiet; or true pyenv activate --quiet; or pyenv deactivate --quiet; or true
else else
pyenv activate --quiet; or true pyenv activate --quiet; or true
end end
EOS
if [ -z "$_has_version_hooks" ]; then
cat <<EOS
set -g _PYENV_VH_PWD "\$PWD"
set -g _PYENV_VH_VERSION "\$PYENV_VERSION"
set -g _PYENV_VH_VENV "\$VIRTUAL_ENV"
set -l d "\$PWD"
set -l _pvh_found_local 0
set -g _PYENV_VH_PATHS
while true
if test -f "\$d/.python-version"; or test -L "\$d/.python-version"
set -g _PYENV_VH_PATHS \$_PYENV_VH_PATHS "\$d/.python-version"
if test -f "\$d/.python-version"
set _pvh_found_local 1
break
end
else
set -g _PYENV_VH_PATHS \$_PYENV_VH_PATHS "\$d"
end
test "\$d" = "/"; and break
set d (string replace -r '/[^/]*\$' '' -- "\$d")
test -z "\$d"; and set d "/"
end
if test "\$_pvh_found_local" = "0"
set -g _PYENV_VH_PATHS \$_PYENV_VH_PATHS "\$PYENV_ROOT/version"
end
set -g _PYENV_VH_MTIMES (stat ${_stat_fmt} \$_PYENV_VH_PATHS 2>/dev/null)
EOS
fi
cat <<EOS
return \$ret return \$ret
end end
EOS
;;
ksh )
cat <<EOS
function _pyenv_virtualenv_hook() {
EOS EOS
;; ;;
* )
bash|zsh )
cat <<EOS cat <<EOS
_pyenv_virtualenv_hook() { _pyenv_virtualenv_hook() {
EOS
;;
esac
if [[ "$shell" != "fish" ]]; then
cat <<EOS
local ret=\$? local ret=\$?
EOS
if [ -z "$_has_version_hooks" ]; then
cat <<EOS
if [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\
&& [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then
if [ -n "\${PYENV_VERSION-}" ]; then
return \$ret
fi
if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\
&& [ "\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)" = "\${_PYENV_VH_MTIMES-}" ]; then
return \$ret
fi
fi
EOS
fi
cat <<EOS
if [ -n "\${VIRTUAL_ENV-}" ]; then if [ -n "\${VIRTUAL_ENV-}" ]; then
eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true
else else
eval "\$(pyenv sh-activate --quiet || true)" || true eval "\$(pyenv sh-activate --quiet || true)" || true
fi fi
EOS
if [ -z "$_has_version_hooks" ]; then
cat <<EOS
_PYENV_VH_PWD="\${PWD}"
_PYENV_VH_VERSION="\${PYENV_VERSION-}"
_PYENV_VH_VENV="\${VIRTUAL_ENV-}"
local _pvh_d="\${PWD}" _pvh_found_local=0
_PYENV_VH_PATHS=()
while :; do
if [ -f "\${_pvh_d}/.python-version" ] || [ -L "\${_pvh_d}/.python-version" ]; then
_PYENV_VH_PATHS+=("\${_pvh_d}/.python-version")
if [ -f "\${_pvh_d}/.python-version" ]; then
_pvh_found_local=1
break
fi
else
_PYENV_VH_PATHS+=("\${_pvh_d}")
fi
[ "\${_pvh_d}" = "/" ] && break
_pvh_d="\${_pvh_d%/*}"
[ -z "\${_pvh_d}" ] && _pvh_d="/"
done
if [ "\${_pvh_found_local}" = "0" ]; then
_PYENV_VH_PATHS+=("\${PYENV_ROOT}/version")
fi
_PYENV_VH_MTIMES="\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)"
EOS
fi
cat <<EOS
return \$ret return \$ret
}; };
EOS EOS
;;
esac
case "$shell" in case "$shell" in
bash ) bash )
cat <<EOS cat <<EOS
if ! [[ "\${PROMPT_COMMAND-}" =~ _pyenv_virtualenv_hook ]]; then if ! [[ "\${PROMPT_COMMAND-}" =~ _pyenv_virtualenv_hook ]]; then
PROMPT_COMMAND="_pyenv_virtualenv_hook;\${PROMPT_COMMAND-}" PROMPT_COMMAND="_pyenv_virtualenv_hook;\${PROMPT_COMMAND-}"
fi fi
EOS EOS
;; ;;
zsh ) zsh )
cat <<EOS cat <<EOS
typeset -g -a precmd_functions typeset -g -a precmd_functions
if [[ -z \$precmd_functions[(r)_pyenv_virtualenv_hook] ]]; then if [[ -z \$precmd_functions[(r)_pyenv_virtualenv_hook] ]]; then
precmd_functions=(_pyenv_virtualenv_hook \$precmd_functions); precmd_functions=(_pyenv_virtualenv_hook \$precmd_functions);
fi fi
EOS EOS
;; ;;
* ) * )
# FIXME: what should i do here?? # No prompt command support or it's installed elsewhere
;; ;;
esac esac
fi

View file

@ -26,13 +26,17 @@ if [ -z "$PYENV_ROOT" ]; then
PYENV_ROOT="${HOME}/.pyenv" PYENV_ROOT="${HOME}/.pyenv"
fi fi
OLDIFS="$IFS"
IFS=:
if [ -n "$1" ]; then if [ -n "$1" ]; then
versions=($@) # $@ is not affected by IFS
IFS=: PYENV_VERSION="${versions[*]}" versions=("$@")
PYENV_VERSION="${versions[*]}"
export PYENV_VERSION export PYENV_VERSION
else else
IFS=: versions=($(pyenv-version-name)) versions=($(pyenv-version-name))
fi fi
IFS="$OLDIFS"
append_virtualenv_prefix() { append_virtualenv_prefix() {
if [ -d "${VIRTUALENV_PREFIX_PATH}" ]; then if [ -d "${VIRTUALENV_PREFIX_PATH}" ]; then
@ -49,7 +53,18 @@ for version in "${versions[@]}"; do
echo "pyenv-virtualenv: version \`${version}' is not a virtualenv" 1>&2 echo "pyenv-virtualenv: version \`${version}' is not a virtualenv" 1>&2
exit 1 exit 1
fi fi
PYENV_PREFIX_PATH="$(pyenv-prefix "${version}")"
# In the vast majority of cases, there's a direct match and
# not spawning `pyenv-prefix' saves about half the invocation time
# with a signle argument which accumulates when called repeatedly
# (e.g. from `pyenv-virtualenvs').
# `pyenv-prefix' also does not have hooks to worry about.
# XXX: refactor the test into a shared module?
PYENV_PREFIX_PATH="${PYENV_ROOT}/versions/${version}"
if [[ ! -d "$PYENV_PREFIX_PATH" ]]; then
PYENV_PREFIX_PATH="$(pyenv-prefix "${version}")"
fi
if [ -x "${PYENV_PREFIX_PATH}/bin/python" ]; then if [ -x "${PYENV_PREFIX_PATH}/bin/python" ]; then
if [ -f "${PYENV_PREFIX_PATH}/bin/activate" ]; then if [ -f "${PYENV_PREFIX_PATH}/bin/activate" ]; then
if [ -f "${PYENV_PREFIX_PATH}/bin/conda" ]; then if [ -f "${PYENV_PREFIX_PATH}/bin/conda" ]; then
@ -94,4 +109,7 @@ for version in "${versions[@]}"; do
fi fi
done done
IFS=: echo "${VIRTUALENV_PREFIX_PATHS[*]}" OLDIFS="$IFS"
IFS=:
echo "${VIRTUALENV_PREFIX_PATHS[*]}"
IFS="$OLDIFS"

View file

@ -6,24 +6,9 @@
# List all virtualenvs found in `$PYENV_ROOT/versions/*' and its `$PYENV_ROOT/versions/envs/*'. # List all virtualenvs found in `$PYENV_ROOT/versions/*' and its `$PYENV_ROOT/versions/envs/*'.
set -e set -e
[ -n "$PYENV_DEBUG" ] && set -x [[ -n $PYENV_DEBUG ]] && set -x
if [ -L "${BASH_SOURCE}" ]; then
READLINK=$(type -p greadlink readlink | head -1)
if [ -z "$READLINK" ]; then
echo "pyenv: cannot find readlink - are you missing GNU coreutils?" >&2
exit 1
fi
resolve_link() {
$READLINK -f "$1"
}
script_path=$(resolve_link ${BASH_SOURCE})
else
script_path=${BASH_SOURCE}
fi
. ${script_path%/*}/../libexec/pyenv-virtualenv-realpath if [[ -z $PYENV_ROOT ]]; then
if [ -z "$PYENV_ROOT" ]; then
PYENV_ROOT="${HOME}/.pyenv" PYENV_ROOT="${HOME}/.pyenv"
fi fi
@ -47,28 +32,26 @@ done
versions_dir="${PYENV_ROOT}/versions" versions_dir="${PYENV_ROOT}/versions"
if [ -d "$versions_dir" ]; then if [[ ${BASH_VERSINFO[0]} -gt 3 ]]; then
versions_dir="$(realpath "$versions_dir")" declare -A current_versions
fi
if [ -n "$bare" ]; then
hit_prefix=""
miss_prefix=""
current_versions=()
unset print_origin
include_system=""
else else
current_versions=()
fi
if [[ -z $bare ]]; then
hit_prefix="* " hit_prefix="* "
miss_prefix=" " miss_prefix=" "
OLDIFS="$IFS" OLDIFS="$IFS"
IFS=: current_versions=($(pyenv-version-name || true)) IFS=:
if [[ ${BASH_VERSINFO[0]} -gt 3 ]]; then
for i in $(pyenv-version-name || true); do
current_versions["$i"]="1"
done
else
read -r -a current_versions <<< "$(pyenv-version-name || true)"
fi
IFS="$OLDIFS" IFS="$OLDIFS"
print_origin="1"
include_system=""
fi fi
num_versions=0
exists() { exists() {
local car="$1" local car="$1"
local cdar local cdar
@ -82,39 +65,67 @@ exists() {
} }
print_version() { print_version() {
if exists "$1" "${current_versions[@]}"; then local version="${1:?}"
echo "${hit_prefix}${1}${print_origin+$2}" if [[ -n $bare ]]; then
else echo "$version"
echo "${miss_prefix}${1}${print_origin+$2}" return
fi
local path="${2:?}"
if [[ -L "$path" ]]; then
version_repr="$version --> $(readlink "$path")"
else
version_repr="$version (created from $(pyenv-virtualenv-prefix "$version" 2>/dev/null))"
fi
if [[ ${BASH_VERSINFO[0]} -gt 3 && ${current_versions["$1"]} ]] || \
{ [[ ${BASH_VERSINFO[0]} -le 3 ]] && exists "$1" "${current_versions[@]}"; }; then
echo "${hit_prefix}${version_repr} (set by $(pyenv-version-origin))"
else
echo "${miss_prefix}${version_repr}"
fi fi
num_versions=$((num_versions + 1))
} }
shopt -s dotglob shopt -s dotglob
shopt -s nullglob shopt -s nullglob
for path in "$versions_dir"/*; do version_dir_entries=("$versions_dir"/*)
if [ -d "$path" ]; then venv_dir_entries=("$versions_dir"/*/envs/*)
if [ -n "$skip_aliases" ] && [ -L "$path" ]; then
target="$(realpath "$path")" if sort --version-sort </dev/null >/dev/null 2>&1; then
[ "${target%/*/envs/*}" != "$versions_dir" ] || continue # system sort supports version sorting
fi OLDIFS="$IFS"
virtualenv_prefix="$(pyenv-virtualenv-prefix "${path##*/}" 2>/dev/null || true)" IFS='||'
if [ -d "${virtualenv_prefix}" ]; then
print_version "${path##*/}" " (created from ${virtualenv_prefix})" read -r -a version_dir_entries <<< "$(
fi printf "%s||" "${version_dir_entries[@]}" |
for venv_path in "${path}/envs/"*; do sort --version-sort
venv="${path##*/}/envs/${venv_path##*/}" )"
virtualenv_prefix="$(pyenv-virtualenv-prefix "${venv}" 2>/dev/null || true)"
if [ -d "${virtualenv_prefix}" ]; then read -r -a venv_dir_entries <<< "$(
print_version "${venv}" " (created from ${virtualenv_prefix})" printf "%s||" "${venv_dir_entries[@]}" |
fi sort --version-sort
done )"
IFS="$OLDIFS"
fi
for env_path in "${venv_dir_entries[@]}"; do
if [[ -d ${env_path} ]]; then
print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}"
fi fi
done done
for env_path in "${version_dir_entries[@]}"; do
if [[ -d ${env_path} ]]; then
if [[ -L ${env_path} ]]; then
if [[ -z $skip_aliases ]]; then
print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}"
fi
# Mimics the test from pyenv-virtualenv-prefix
# XXX: refactor itto a shared module ?
elif [[ -f "${env_path}/bin/activate" ]]; then
print_version "${env_path#"${PYENV_ROOT}"/versions/}" "${env_path}"
fi
fi
done
shopt -u dotglob shopt -u dotglob
shopt -u nullglob shopt -u nullglob
if [ "$num_versions" -eq 0 ] && [ -n "$include_system" ]; then
echo "Warning: no Python virtualenv detected on the system" >&2
exit 1
fi

View file

@ -15,7 +15,9 @@ setup() {
unset PYENV_VIRTUALENV_DISABLE_PROMPT unset PYENV_VIRTUALENV_DISABLE_PROMPT
unset PYENV_VIRTUAL_ENV_DISABLE_PROMPT unset PYENV_VIRTUAL_ENV_DISABLE_PROMPT
unset VIRTUAL_ENV_DISABLE_PROMPT unset VIRTUAL_ENV_DISABLE_PROMPT
unset PYENV_VIRTUALENV_PROMPT
unset _OLD_VIRTUAL_PS1 unset _OLD_VIRTUAL_PS1
stub pyenv-hooks "activate : echo"
} }
@test "activate virtualenv from current version" { @test "activate virtualenv from current version" {
@ -33,7 +35,6 @@ setup() {
deactivated deactivated
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv"; export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv"; export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv";
pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(venv) \${PS1:-}"; export PS1="(venv) \${PS1:-}";
EOS EOS
@ -44,6 +45,31 @@ EOS
unstub pyenv-sh-deactivate unstub pyenv-sh-deactivate
} }
@test "activate virtualenv from current version with custom prompt" {
export PYENV_VIRTUALENV_INIT=1
stub pyenv-version-name "echo venv"
stub pyenv-virtualenv-prefix "venv : echo \"${PYENV_ROOT}/versions/venv\""
stub pyenv-prefix "venv : echo \"${PYENV_ROOT}/versions/venv\""
stub pyenv-sh-deactivate "--force --quiet : echo deactivated"
PYENV_SHELL="bash" PYENV_VERSION="venv" PYENV_VIRTUALENV_PROMPT='venv:{venv}' run pyenv-sh-activate
assert_success
assert_output <<EOS
deactivated
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv";
export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="venv:venv \${PS1:-}";
EOS
unstub pyenv-version-name
unstub pyenv-virtualenv-prefix
unstub pyenv-prefix
unstub pyenv-sh-deactivate
}
@test "activate virtualenv from current version (quiet)" { @test "activate virtualenv from current version (quiet)" {
export PYENV_VIRTUALENV_INIT=1 export PYENV_VIRTUALENV_INIT=1
@ -86,7 +112,6 @@ deactivated
pyenv-virtualenv: activate venv pyenv-virtualenv: activate venv
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv"; export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv"; export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv";
pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(venv) \${PS1:-}"; export PS1="(venv) \${PS1:-}";
EOS EOS
@ -114,7 +139,6 @@ export PYENV_VERSION="venv";
export PYENV_ACTIVATE_SHELL=1; export PYENV_ACTIVATE_SHELL=1;
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv"; export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv"; export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv";
pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(venv) \${PS1:-}"; export PS1="(venv) \${PS1:-}";
EOS EOS
@ -140,7 +164,18 @@ EOS
deactivated deactivated
set -gx PYENV_VIRTUAL_ENV "${PYENV_ROOT}/versions/venv"; set -gx PYENV_VIRTUAL_ENV "${PYENV_ROOT}/versions/venv";
set -gx VIRTUAL_ENV "${PYENV_ROOT}/versions/venv"; set -gx VIRTUAL_ENV "${PYENV_ROOT}/versions/venv";
pyenv-virtualenv: prompt changing not working for fish. functions -e _pyenv_old_prompt # remove old prompt function if exists.
# since everything is in memory, it's safe to
# remove it.
functions -c fish_prompt _pyenv_old_prompt # backup old prompt function
# from python-venv
function fish_prompt
set -l prompt (_pyenv_old_prompt) # call old prompt function first since it might
# read exit status
echo -n "(venv) " # add virtualenv to prompt
string join -- \n \$prompt # handle multiline prompts
end
EOS EOS
unstub pyenv-version-name unstub pyenv-version-name
@ -166,7 +201,18 @@ set -gx PYENV_VERSION "venv";
set -gx PYENV_ACTIVATE_SHELL 1; set -gx PYENV_ACTIVATE_SHELL 1;
set -gx PYENV_VIRTUAL_ENV "${PYENV_ROOT}/versions/venv"; set -gx PYENV_VIRTUAL_ENV "${PYENV_ROOT}/versions/venv";
set -gx VIRTUAL_ENV "${PYENV_ROOT}/versions/venv"; set -gx VIRTUAL_ENV "${PYENV_ROOT}/versions/venv";
pyenv-virtualenv: prompt changing not working for fish. functions -e _pyenv_old_prompt # remove old prompt function if exists.
# since everything is in memory, it's safe to
# remove it.
functions -c fish_prompt _pyenv_old_prompt # backup old prompt function
# from python-venv
function fish_prompt
set -l prompt (_pyenv_old_prompt) # call old prompt function first since it might
# read exit status
echo -n "(venv) " # add virtualenv to prompt
string join -- \n \$prompt # handle multiline prompts
end
EOS EOS
unstub pyenv-version-name unstub pyenv-version-name
@ -191,7 +237,6 @@ export PYENV_VERSION="venv27";
export PYENV_ACTIVATE_SHELL=1; export PYENV_ACTIVATE_SHELL=1;
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27"; export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27"; export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27";
pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(venv27) \${PS1:-}"; export PS1="(venv27) \${PS1:-}";
EOS EOS
@ -217,7 +262,6 @@ export PYENV_VERSION="venv27";
export PYENV_ACTIVATE_SHELL=1; export PYENV_ACTIVATE_SHELL=1;
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27"; export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27"; export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27";
pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(venv27) \${PS1:-}"; export PS1="(venv27) \${PS1:-}";
EOS EOS
@ -243,7 +287,18 @@ set -gx PYENV_VERSION "venv27";
set -gx PYENV_ACTIVATE_SHELL 1; set -gx PYENV_ACTIVATE_SHELL 1;
set -gx PYENV_VIRTUAL_ENV "${PYENV_ROOT}/versions/venv27"; set -gx PYENV_VIRTUAL_ENV "${PYENV_ROOT}/versions/venv27";
set -gx VIRTUAL_ENV "${PYENV_ROOT}/versions/venv27"; set -gx VIRTUAL_ENV "${PYENV_ROOT}/versions/venv27";
pyenv-virtualenv: prompt changing not working for fish. functions -e _pyenv_old_prompt # remove old prompt function if exists.
# since everything is in memory, it's safe to
# remove it.
functions -c fish_prompt _pyenv_old_prompt # backup old prompt function
# from python-venv
function fish_prompt
set -l prompt (_pyenv_old_prompt) # call old prompt function first since it might
# read exit status
echo -n "(venv27) " # add virtualenv to prompt
string join -- \n \$prompt # handle multiline prompts
end
EOS EOS
unstub pyenv-virtualenv-prefix unstub pyenv-virtualenv-prefix
@ -267,7 +322,18 @@ set -gx PYENV_VERSION "venv27";
set -gx PYENV_ACTIVATE_SHELL 1; set -gx PYENV_ACTIVATE_SHELL 1;
set -gx PYENV_VIRTUAL_ENV "${PYENV_ROOT}/versions/venv27"; set -gx PYENV_VIRTUAL_ENV "${PYENV_ROOT}/versions/venv27";
set -gx VIRTUAL_ENV "${PYENV_ROOT}/versions/venv27"; set -gx VIRTUAL_ENV "${PYENV_ROOT}/versions/venv27";
pyenv-virtualenv: prompt changing not working for fish. functions -e _pyenv_old_prompt # remove old prompt function if exists.
# since everything is in memory, it's safe to
# remove it.
functions -c fish_prompt _pyenv_old_prompt # backup old prompt function
# from python-venv
function fish_prompt
set -l prompt (_pyenv_old_prompt) # call old prompt function first since it might
# read exit status
echo -n "(venv27) " # add virtualenv to prompt
string join -- \n \$prompt # handle multiline prompts
end
EOS EOS
unstub pyenv-virtualenv-prefix unstub pyenv-virtualenv-prefix
@ -390,7 +456,6 @@ export PYENV_VERSION="venv27:2.7.10";
export PYENV_ACTIVATE_SHELL=1; export PYENV_ACTIVATE_SHELL=1;
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27"; export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27"; export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv27";
pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(venv27) \${PS1:-}"; export PS1="(venv27) \${PS1:-}";
EOS EOS
@ -400,6 +465,34 @@ EOS
unstub pyenv-prefix unstub pyenv-prefix
} }
@test "do nothing if a 3rd-party virtualenv is active" {
export PYENV_VIRTUALENV_INIT=1
export VIRTUAL_ENV="${TMP}/venv-3rd-party"
unset PYENV_VIRTUAL_ENV
PYENV_SHELL="bash" run pyenv-sh-activate "venv"
assert_success
assert_output <<EOS
pyenv-virtualenv: virtualenv \`${TMP}/venv-3rd-party' is already activated
true
EOS
}
@test "do nothing if a 3rd-party virtualenv is active over ours" {
export PYENV_VIRTUALENV_INIT=1
export VIRTUAL_ENV="${TMP}/venv-3rd-party"
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv"
PYENV_SHELL="bash" run pyenv-sh-activate "venv"
assert_success
assert_output <<EOS
pyenv-virtualenv: virtualenv \`${TMP}/venv-3rd-party' is already activated
true
EOS
}
@test "should fail if activate is invoked as a command" { @test "should fail if activate is invoked as a command" {
run pyenv-activate run pyenv-activate

View file

@ -16,7 +16,13 @@ setup() {
unset PYENV_VIRTUALENV_DISABLE_PROMPT unset PYENV_VIRTUALENV_DISABLE_PROMPT
unset PYENV_VIRTUAL_ENV_DISABLE_PROMPT unset PYENV_VIRTUAL_ENV_DISABLE_PROMPT
unset VIRTUAL_ENV_DISABLE_PROMPT unset VIRTUAL_ENV_DISABLE_PROMPT
unset PYENV_VIRTUALENV_PROMPT
unset _OLD_VIRTUAL_PS1 unset _OLD_VIRTUAL_PS1
stub pyenv-hooks "activate : echo"
}
teardown() {
unstub pyenv-hooks
} }
@test "activate conda root from current version" { @test "activate conda root from current version" {
@ -36,7 +42,6 @@ deactivated
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/anaconda-2.3.0"; export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/anaconda-2.3.0";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/anaconda-2.3.0"; export VIRTUAL_ENV="${PYENV_ROOT}/versions/anaconda-2.3.0";
export CONDA_DEFAULT_ENV="root"; export CONDA_DEFAULT_ENV="root";
pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(anaconda-2.3.0) \${PS1:-}"; export PS1="(anaconda-2.3.0) \${PS1:-}";
export CONDA_PREFIX="${TMP}/pyenv/versions/anaconda-2.3.0"; export CONDA_PREFIX="${TMP}/pyenv/versions/anaconda-2.3.0";
@ -49,6 +54,35 @@ EOS
teardown_conda "anaconda-2.3.0" teardown_conda "anaconda-2.3.0"
} }
@test "activate conda root from current version with custom prompt" {
export PYENV_VIRTUALENV_INIT=1
setup_conda "anaconda-2.3.0"
stub pyenv-version-name "echo anaconda-2.3.0"
stub pyenv-virtualenv-prefix "anaconda-2.3.0 : echo \"${PYENV_ROOT}/versions/anaconda-2.3.0\""
stub pyenv-prefix "anaconda-2.3.0 : echo \"${PYENV_ROOT}/versions/anaconda-2.3.0\""
stub pyenv-sh-deactivate "--force --quiet : echo deactivated"
PYENV_SHELL="bash" PYENV_VERSION="anaconda-2.3.0" PYENV_VIRTUALENV_PROMPT='venv:{venv}' run pyenv-sh-activate
assert_success
assert_output <<EOS
deactivated
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/anaconda-2.3.0";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/anaconda-2.3.0";
export CONDA_DEFAULT_ENV="root";
export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="venv:anaconda-2.3.0 \${PS1:-}";
export CONDA_PREFIX="${TMP}/pyenv/versions/anaconda-2.3.0";
EOS
unstub pyenv-version-name
unstub pyenv-virtualenv-prefix
unstub pyenv-prefix
unstub pyenv-sh-deactivate
teardown_conda "anaconda-2.3.0"
}
@test "activate conda root from current version (fish)" { @test "activate conda root from current version (fish)" {
export PYENV_VIRTUALENV_INIT=1 export PYENV_VIRTUALENV_INIT=1
@ -66,7 +100,18 @@ deactivated
set -gx PYENV_VIRTUAL_ENV "${TMP}/pyenv/versions/anaconda-2.3.0"; set -gx PYENV_VIRTUAL_ENV "${TMP}/pyenv/versions/anaconda-2.3.0";
set -gx VIRTUAL_ENV "${TMP}/pyenv/versions/anaconda-2.3.0"; set -gx VIRTUAL_ENV "${TMP}/pyenv/versions/anaconda-2.3.0";
set -gx CONDA_DEFAULT_ENV "root"; set -gx CONDA_DEFAULT_ENV "root";
pyenv-virtualenv: prompt changing not working for fish. functions -e _pyenv_old_prompt # remove old prompt function if exists.
# since everything is in memory, it's safe to
# remove it.
functions -c fish_prompt _pyenv_old_prompt # backup old prompt function
# from python-venv
function fish_prompt
set -l prompt (_pyenv_old_prompt) # call old prompt function first since it might
# read exit status
echo -n "(anaconda-2.3.0) " # add virtualenv to prompt
string join -- \n \$prompt # handle multiline prompts
end
EOS EOS
unstub pyenv-version-name unstub pyenv-version-name
@ -95,7 +140,6 @@ export PYENV_ACTIVATE_SHELL=1;
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/miniconda-3.9.1"; export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/miniconda-3.9.1";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/miniconda-3.9.1"; export VIRTUAL_ENV="${PYENV_ROOT}/versions/miniconda-3.9.1";
export CONDA_DEFAULT_ENV="root"; export CONDA_DEFAULT_ENV="root";
pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(miniconda-3.9.1) \${PS1:-}"; export PS1="(miniconda-3.9.1) \${PS1:-}";
export CONDA_PREFIX="${TMP}/pyenv/versions/miniconda-3.9.1"; export CONDA_PREFIX="${TMP}/pyenv/versions/miniconda-3.9.1";
@ -125,7 +169,6 @@ deactivated
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/anaconda-2.3.0/envs/foo"; export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/anaconda-2.3.0/envs/foo";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/anaconda-2.3.0/envs/foo"; export VIRTUAL_ENV="${PYENV_ROOT}/versions/anaconda-2.3.0/envs/foo";
export CONDA_DEFAULT_ENV="foo"; export CONDA_DEFAULT_ENV="foo";
pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(anaconda-2.3.0/envs/foo) \${PS1:-}"; export PS1="(anaconda-2.3.0/envs/foo) \${PS1:-}";
export CONDA_PREFIX="${TMP}/pyenv/versions/anaconda-2.3.0/envs/foo"; export CONDA_PREFIX="${TMP}/pyenv/versions/anaconda-2.3.0/envs/foo";
@ -158,7 +201,6 @@ export PYENV_ACTIVATE_SHELL=1;
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/miniconda-3.9.1/envs/bar"; export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/miniconda-3.9.1/envs/bar";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/miniconda-3.9.1/envs/bar"; export VIRTUAL_ENV="${PYENV_ROOT}/versions/miniconda-3.9.1/envs/bar";
export CONDA_DEFAULT_ENV="bar"; export CONDA_DEFAULT_ENV="bar";
pyenv-virtualenv: prompt changing will be removed from future release. configure \`export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
export _OLD_VIRTUAL_PS1="\${PS1:-}"; export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(miniconda-3.9.1/envs/bar) \${PS1:-}"; export PS1="(miniconda-3.9.1/envs/bar) \${PS1:-}";
export CONDA_PREFIX="${TMP}/pyenv/versions/miniconda-3.9.1/envs/bar"; export CONDA_PREFIX="${TMP}/pyenv/versions/miniconda-3.9.1/envs/bar";

View file

@ -16,6 +16,11 @@ setup() {
unset PYENV_VIRTUAL_ENV_DISABLE_PROMPT unset PYENV_VIRTUAL_ENV_DISABLE_PROMPT
unset VIRTUAL_ENV_DISABLE_PROMPT unset VIRTUAL_ENV_DISABLE_PROMPT
unset _OLD_VIRTUAL_PS1 unset _OLD_VIRTUAL_PS1
stub pyenv-hooks "deactivate : echo"
}
teardown() {
unstub pyenv-hooks
} }
@test "deactivate conda root" { @test "deactivate conda root" {
@ -77,6 +82,13 @@ if [ -n "\$_OLD_VIRTUAL_PYTHONHOME" ];
set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME"; set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME";
set -e _OLD_VIRTUAL_PYTHONHOME; set -e _OLD_VIRTUAL_PYTHONHOME;
end; end;
# check if old prompt function exists
if functions -q _pyenv_old_prompt
# remove old prompt function if exists.
functions -e fish_prompt
functions -c _pyenv_old_prompt fish_prompt
functions -e _pyenv_old_prompt
end
if functions -q deactivate; if functions -q deactivate;
functions -e deactivate; functions -e deactivate;
end; end;

View file

@ -9,7 +9,6 @@ setup() {
@test "display conda root" { @test "display conda root" {
setup_conda "anaconda-2.3.0" setup_conda "anaconda-2.3.0"
stub pyenv-version-name "echo anaconda-2.3.0" stub pyenv-version-name "echo anaconda-2.3.0"
stub pyenv-prefix "anaconda-2.3.0 : echo \"${PYENV_ROOT}/versions/anaconda-2.3.0\""
PYENV_VERSION="anaconda-2.3.0" run pyenv-virtualenv-prefix PYENV_VERSION="anaconda-2.3.0" run pyenv-virtualenv-prefix
@ -19,14 +18,12 @@ ${PYENV_ROOT}/versions/anaconda-2.3.0
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
teardown_conda "anaconda-2.3.0" teardown_conda "anaconda-2.3.0"
} }
@test "display conda env" { @test "display conda env" {
setup_conda "anaconda-2.3.0" "foo" setup_conda "anaconda-2.3.0" "foo"
stub pyenv-version-name "echo anaconda-2.3.0/envs/foo" stub pyenv-version-name "echo anaconda-2.3.0/envs/foo"
stub pyenv-prefix "anaconda-2.3.0/envs/foo : echo \"${PYENV_ROOT}/versions/anaconda-2.3.0/envs/foo\""
PYENV_VERSION="anaconda-2.3.0/envs/foo" run pyenv-virtualenv-prefix PYENV_VERSION="anaconda-2.3.0/envs/foo" run pyenv-virtualenv-prefix
@ -36,6 +33,5 @@ ${PYENV_ROOT}/versions/anaconda-2.3.0/envs/foo
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
teardown_conda "anaconda-2.3.0" "foo" teardown_conda "anaconda-2.3.0" "foo"
} }

View file

@ -26,14 +26,15 @@ unstub_pyenv() {
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-virtualenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-exec "conda * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub -N pyenv-exec "conda list * : true"
stub -N pyenv-exec "conda create * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : true" stub pyenv-exec "python -s -m ensurepip : true"
run pyenv-virtualenv venv run pyenv-virtualenv venv
assert_success assert_success
assert_output <<OUT assert_output_wildcards <<OUT
PYENV_VERSION=miniconda3-3.16.0 conda create --name venv --yes python PYENV_VERSION=miniconda3-3.16.0 conda create --name venv --yes --file /dev/fd/*
rehashed rehashed
OUT OUT
@ -49,14 +50,14 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-virtualenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-exec "conda * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "conda create * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : true" stub pyenv-exec "python -s -m ensurepip : true"
run pyenv-virtualenv -p python3.5 venv run pyenv-virtualenv -p python3.5 venv
assert_success assert_success
assert_output <<OUT assert_output <<OUT
PYENV_VERSION=miniconda3-3.16.0 conda create --name venv --yes python=3.5 python PYENV_VERSION=miniconda3-3.16.0 conda create --name venv --yes python=3.5
rehashed rehashed
OUT OUT
@ -72,14 +73,14 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-virtualenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-exec "conda * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "conda create * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : true" stub pyenv-exec "python -s -m ensurepip : true"
run pyenv-virtualenv --python=python3.5 venv run pyenv-virtualenv --python=python3.5 venv
assert_success assert_success
assert_output <<OUT assert_output <<OUT
PYENV_VERSION=miniconda3-3.16.0 conda create --name venv --yes python=3.5 python PYENV_VERSION=miniconda3-3.16.0 conda create --name venv --yes python=3.5
rehashed rehashed
OUT OUT

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bats #!/usr/bin/env bats
load test_helper load test_helper
@ -16,6 +16,7 @@ setup() {
unset PYENV_VIRTUAL_ENV_DISABLE_PROMPT unset PYENV_VIRTUAL_ENV_DISABLE_PROMPT
unset VIRTUAL_ENV_DISABLE_PROMPT unset VIRTUAL_ENV_DISABLE_PROMPT
unset _OLD_VIRTUAL_PS1 unset _OLD_VIRTUAL_PS1
stub pyenv-hooks "deactivate : echo"
} }
@test "deactivate virtualenv" { @test "deactivate virtualenv" {
@ -224,6 +225,13 @@ if [ -n "\$_OLD_VIRTUAL_PYTHONHOME" ];
set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME"; set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME";
set -e _OLD_VIRTUAL_PYTHONHOME; set -e _OLD_VIRTUAL_PYTHONHOME;
end; end;
# check if old prompt function exists
if functions -q _pyenv_old_prompt
# remove old prompt function if exists.
functions -e fish_prompt
functions -c _pyenv_old_prompt fish_prompt
functions -e _pyenv_old_prompt
end
if functions -q deactivate; if functions -q deactivate;
functions -e deactivate; functions -e deactivate;
end; end;
@ -250,6 +258,13 @@ if [ -n "\$_OLD_VIRTUAL_PYTHONHOME" ];
set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME"; set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME";
set -e _OLD_VIRTUAL_PYTHONHOME; set -e _OLD_VIRTUAL_PYTHONHOME;
end; end;
# check if old prompt function exists
if functions -q _pyenv_old_prompt
# remove old prompt function if exists.
functions -e fish_prompt
functions -c _pyenv_old_prompt fish_prompt
functions -e _pyenv_old_prompt
end
if functions -q deactivate; if functions -q deactivate;
functions -e deactivate; functions -e deactivate;
end; end;
@ -278,6 +293,13 @@ if [ -n "\$_OLD_VIRTUAL_PYTHONHOME" ];
set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME"; set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME";
set -e _OLD_VIRTUAL_PYTHONHOME; set -e _OLD_VIRTUAL_PYTHONHOME;
end; end;
# check if old prompt function exists
if functions -q _pyenv_old_prompt
# remove old prompt function if exists.
functions -e fish_prompt
functions -c _pyenv_old_prompt fish_prompt
functions -e _pyenv_old_prompt
end
if functions -q deactivate; if functions -q deactivate;
functions -e deactivate; functions -e deactivate;
end; end;
@ -306,6 +328,13 @@ if [ -n "\$_OLD_VIRTUAL_PYTHONHOME" ];
set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME"; set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME";
set -e _OLD_VIRTUAL_PYTHONHOME; set -e _OLD_VIRTUAL_PYTHONHOME;
end; end;
# check if old prompt function exists
if functions -q _pyenv_old_prompt
# remove old prompt function if exists.
functions -e fish_prompt
functions -c _pyenv_old_prompt fish_prompt
functions -e _pyenv_old_prompt
end
if functions -q deactivate; if functions -q deactivate;
functions -e deactivate; functions -e deactivate;
end; end;
@ -332,6 +361,13 @@ if [ -n "\$_OLD_VIRTUAL_PYTHONHOME" ];
set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME"; set -gx PYTHONHOME "\$_OLD_VIRTUAL_PYTHONHOME";
set -e _OLD_VIRTUAL_PYTHONHOME; set -e _OLD_VIRTUAL_PYTHONHOME;
end; end;
# check if old prompt function exists
if functions -q _pyenv_old_prompt
# remove old prompt function if exists.
functions -e fish_prompt
functions -c _pyenv_old_prompt fish_prompt
functions -e _pyenv_old_prompt
end
if functions -q deactivate; if functions -q deactivate;
functions -e deactivate; functions -e deactivate;
end; end;

View file

@ -25,15 +25,15 @@ unstub_pyenv() {
stub pyenv-version-name "echo '${PYENV_VERSION}'" stub pyenv-version-name "echo '${PYENV_VERSION}'"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python3.5 -m venv --help : true" stub pyenv-exec "python -m venv --help : true"
stub pyenv-exec "python3.5 -m venv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";mkdir -p \${PYENV_ROOT}/versions/3.5.1/envs/venv/bin" stub pyenv-exec "python -m venv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";mkdir -p \${PYENV_ROOT}/versions/3.5.1/envs/venv/bin"
stub pyenv-exec "python -s -m ensurepip : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";touch \${PYENV_ROOT}/versions/3.5.1/envs/venv/bin/pip" stub pyenv-exec "python -s -m ensurepip : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";touch \${PYENV_ROOT}/versions/3.5.1/envs/venv/bin/pip"
run pyenv-virtualenv venv run pyenv-virtualenv venv
assert_success assert_success
assert_output <<OUT assert_output <<OUT
PYENV_VERSION=3.5.1 python3.5 -m venv ${PYENV_ROOT}/versions/3.5.1/envs/venv PYENV_VERSION=3.5.1 python -m venv ${PYENV_ROOT}/versions/3.5.1/envs/venv
PYENV_VERSION=3.5.1/envs/venv python -s -m ensurepip PYENV_VERSION=3.5.1/envs/venv python -s -m ensurepip
rehashed rehashed
OUT OUT

View file

@ -6,6 +6,7 @@ setup() {
export PYENV_ROOT="${TMP}/pyenv" export PYENV_ROOT="${TMP}/pyenv"
export HOOK_PATH="${TMP}/i has hooks" export HOOK_PATH="${TMP}/i has hooks"
mkdir -p "$HOOK_PATH" mkdir -p "$HOOK_PATH"
unset PYENV_VIRTUALENV_PROMPT
} }
@test "pyenv-virtualenv hooks" { @test "pyenv-virtualenv hooks" {
@ -17,7 +18,7 @@ OUT
create_executable "3.5.1" "virtualenv" create_executable "3.5.1" "virtualenv"
stub pyenv-prefix "echo '${PYENV_ROOT}/versions/3.5.1'" stub pyenv-prefix "echo '${PYENV_ROOT}/versions/3.5.1'"
stub pyenv-prefix "echo '${PYENV_ROOT}/versions/3.5.1'" stub pyenv-prefix "echo '${PYENV_ROOT}/versions/3.5.1'"
stub pyenv-exec "python3.5 -m venv --help : true" stub pyenv-exec "python -m venv --help : true"
stub pyenv-hooks "virtualenv : echo '$HOOK_PATH'/virtualenv.bash" stub pyenv-hooks "virtualenv : echo '$HOOK_PATH'/virtualenv.bash"
stub pyenv-exec "echo PYENV_VERSION=3.5.1 \"\$@\"" stub pyenv-exec "echo PYENV_VERSION=3.5.1 \"\$@\""
stub pyenv-exec "echo PYENV_VERSION=3.5.1 \"\$@\"" stub pyenv-exec "echo PYENV_VERSION=3.5.1 \"\$@\""
@ -40,3 +41,74 @@ OUT
unstub pyenv-rehash unstub pyenv-rehash
teardown_version "3.5.1" teardown_version "3.5.1"
} }
@test "pyenv-sh-activate hooks" {
cat > "${HOOK_PATH}/activate.bash" <<OUT
before_activate 'echo "before"'
after_activate 'echo "after"'
OUT
export PYENV_VIRTUALENV_INIT=1
stub pyenv-version-name "echo venv"
stub pyenv-virtualenv-prefix ""
stub pyenv-prefix "venv : echo \"${PYENV_ROOT}/versions/venv\""
stub pyenv-hooks "activate : echo '$HOOK_PATH'/activate.bash"
stub pyenv-sh-deactivate ""
PYENV_SHELL="bash" PYENV_VERSION="venv" run pyenv-sh-activate
assert_success
assert_output <<EOS
before
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv";
export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv";
export _OLD_VIRTUAL_PS1="\${PS1:-}";
export PS1="(venv) \${PS1:-}";
after
EOS
unstub pyenv-version-name
unstub pyenv-virtualenv-prefix
unstub pyenv-prefix
unstub pyenv-hooks
unstub pyenv-sh-deactivate
}
@test "deactivate virtualenv" {
cat > "${HOOK_PATH}/deactivate.bash" <<OUT
before_deactivate 'echo "before"'
after_deactivate 'echo "after"'
OUT
export PYENV_VIRTUALENV_INIT=1
export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv"
export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv"
export PYENV_ACTIVATE_SHELL=
stub pyenv-hooks "deactivate : echo '$HOOK_PATH'/deactivate.bash"
PYENV_SHELL="bash" run pyenv-sh-deactivate
assert_success
assert_output <<EOS
before
unset PYENV_VIRTUAL_ENV;
unset VIRTUAL_ENV;
if [ -n "\${_OLD_VIRTUAL_PATH:-}" ]; then
export PATH="\${_OLD_VIRTUAL_PATH}";
unset _OLD_VIRTUAL_PATH;
fi;
if [ -n "\${_OLD_VIRTUAL_PYTHONHOME:-}" ]; then
export PYTHONHOME="\${_OLD_VIRTUAL_PYTHONHOME}";
unset _OLD_VIRTUAL_PYTHONHOME;
fi;
if [ -n "\${_OLD_VIRTUAL_PS1:-}" ]; then
export PS1="\${_OLD_VIRTUAL_PS1}";
unset _OLD_VIRTUAL_PS1;
fi;
if declare -f deactivate 1>/dev/null 2>&1; then
unset -f deactivate;
fi;
after
EOS
unstub pyenv-hooks
}

View file

@ -29,22 +29,18 @@ load test_helper
rm -f "${TMP}/script.sh" rm -f "${TMP}/script.sh"
} }
@test "sh-compatible instructions" {
run pyenv-virtualenv-init bash
assert [ "$status" -eq 1 ]
assert_output_contains 'eval "$(pyenv virtualenv-init -)"'
run pyenv-virtualenv-init zsh
assert [ "$status" -eq 1 ]
assert_output_contains 'eval "$(pyenv virtualenv-init -)"'
}
@test "fish instructions" { @test "fish instructions" {
run pyenv-virtualenv-init fish run pyenv-virtualenv-init fish
assert [ "$status" -eq 1 ] assert [ "$status" -eq 1 ]
assert_output_contains 'status --is-interactive; and source (pyenv virtualenv-init -|psub)' assert_output_contains 'status --is-interactive; and source (pyenv virtualenv-init -|psub)'
} }
@test "other shells instructions" {
run pyenv-virtualenv-init some_other_sh
assert [ "$status" -eq 1 ]
assert_output_contains 'eval "$(pyenv virtualenv-init -)"'
}
@test "outputs bash-specific syntax" { @test "outputs bash-specific syntax" {
export PYENV_VIRTUALENV_ROOT="${TMP}/pyenv/plugins/pyenv-virtualenv" export PYENV_VIRTUALENV_ROOT="${TMP}/pyenv/plugins/pyenv-virtualenv"
run pyenv-virtualenv-init - bash run pyenv-virtualenv-init - bash
@ -54,11 +50,44 @@ export PATH="${TMP}/pyenv/plugins/pyenv-virtualenv/shims:\${PATH}";
export PYENV_VIRTUALENV_INIT=1; export PYENV_VIRTUALENV_INIT=1;
_pyenv_virtualenv_hook() { _pyenv_virtualenv_hook() {
local ret=\$? local ret=\$?
if [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\
&& [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then
if [ -n "\${PYENV_VERSION-}" ]; then
return \$ret
fi
if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\
&& [ "\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)" = "\${_PYENV_VH_MTIMES-}" ]; then
return \$ret
fi
fi
if [ -n "\${VIRTUAL_ENV-}" ]; then if [ -n "\${VIRTUAL_ENV-}" ]; then
eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true
else else
eval "\$(pyenv sh-activate --quiet || true)" || true eval "\$(pyenv sh-activate --quiet || true)" || true
fi fi
_PYENV_VH_PWD="\${PWD}"
_PYENV_VH_VERSION="\${PYENV_VERSION-}"
_PYENV_VH_VENV="\${VIRTUAL_ENV-}"
local _pvh_d="\${PWD}" _pvh_found_local=0
_PYENV_VH_PATHS=()
while :; do
if [ -f "\${_pvh_d}/.python-version" ] || [ -L "\${_pvh_d}/.python-version" ]; then
_PYENV_VH_PATHS+=("\${_pvh_d}/.python-version")
if [ -f "\${_pvh_d}/.python-version" ]; then
_pvh_found_local=1
break
fi
else
_PYENV_VH_PATHS+=("\${_pvh_d}")
fi
[ "\${_pvh_d}" = "/" ] && break
_pvh_d="\${_pvh_d%/*}"
[ -z "\${_pvh_d}" ] && _pvh_d="/"
done
if [ "\${_pvh_found_local}" = "0" ]; then
_PYENV_VH_PATHS+=("\${PYENV_ROOT}/version")
fi
_PYENV_VH_MTIMES="\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)"
return \$ret return \$ret
}; };
if ! [[ "\${PROMPT_COMMAND-}" =~ _pyenv_virtualenv_hook ]]; then if ! [[ "\${PROMPT_COMMAND-}" =~ _pyenv_virtualenv_hook ]]; then
@ -78,11 +107,45 @@ set -gx PATH '${TMP}/pyenv/plugins/pyenv-virtualenv/shims' \$PATH;
set -gx PYENV_VIRTUALENV_INIT 1; set -gx PYENV_VIRTUALENV_INIT 1;
function _pyenv_virtualenv_hook --on-event fish_prompt; function _pyenv_virtualenv_hook --on-event fish_prompt;
set -l ret \$status set -l ret \$status
if test "\$PYENV_VERSION" = "\$_PYENV_VH_VERSION" \\
-a "\$VIRTUAL_ENV" = "\$_PYENV_VH_VENV"
if test -n "\$PYENV_VERSION"
return \$ret
end
if test "\$PWD" = "\$_PYENV_VH_PWD" \\
-a "(stat ${_stat_fmt} \$_PYENV_VH_PATHS 2>/dev/null)" = "\$_PYENV_VH_MTIMES"
return \$ret
end
end
if [ -n "\$VIRTUAL_ENV" ] if [ -n "\$VIRTUAL_ENV" ]
pyenv activate --quiet; or pyenv deactivate --quiet; or true pyenv activate --quiet; or pyenv deactivate --quiet; or true
else else
pyenv activate --quiet; or true pyenv activate --quiet; or true
end end
set -g _PYENV_VH_PWD "\$PWD"
set -g _PYENV_VH_VERSION "\$PYENV_VERSION"
set -g _PYENV_VH_VENV "\$VIRTUAL_ENV"
set -l d "\$PWD"
set -l _pvh_found_local 0
set -g _PYENV_VH_PATHS
while true
if test -f "\$d/.python-version"; or test -L "\$d/.python-version"
set -g _PYENV_VH_PATHS \$_PYENV_VH_PATHS "\$d/.python-version"
if test -f "\$d/.python-version"
set _pvh_found_local 1
break
end
else
set -g _PYENV_VH_PATHS \$_PYENV_VH_PATHS "\$d"
end
test "\$d" = "/"; and break
set d (string replace -r '/[^/]*\$' '' -- "\$d")
test -z "\$d"; and set d "/"
end
if test "\$_pvh_found_local" = "0"
set -g _PYENV_VH_PATHS \$_PYENV_VH_PATHS "\$PYENV_ROOT/version"
end
set -g _PYENV_VH_MTIMES (stat ${_stat_fmt} \$_PYENV_VH_PATHS 2>/dev/null)
return \$ret return \$ret
end end
EOS EOS
@ -97,11 +160,44 @@ export PATH="${TMP}/pyenv/plugins/pyenv-virtualenv/shims:\${PATH}";
export PYENV_VIRTUALENV_INIT=1; export PYENV_VIRTUALENV_INIT=1;
_pyenv_virtualenv_hook() { _pyenv_virtualenv_hook() {
local ret=\$? local ret=\$?
if [ "\${PYENV_VERSION-}" = "\${_PYENV_VH_VERSION-}" ] \\
&& [ "\${VIRTUAL_ENV-}" = "\${_PYENV_VH_VENV-}" ]; then
if [ -n "\${PYENV_VERSION-}" ]; then
return \$ret
fi
if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\
&& [ "\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)" = "\${_PYENV_VH_MTIMES-}" ]; then
return \$ret
fi
fi
if [ -n "\${VIRTUAL_ENV-}" ]; then if [ -n "\${VIRTUAL_ENV-}" ]; then
eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true
else else
eval "\$(pyenv sh-activate --quiet || true)" || true eval "\$(pyenv sh-activate --quiet || true)" || true
fi fi
_PYENV_VH_PWD="\${PWD}"
_PYENV_VH_VERSION="\${PYENV_VERSION-}"
_PYENV_VH_VENV="\${VIRTUAL_ENV-}"
local _pvh_d="\${PWD}" _pvh_found_local=0
_PYENV_VH_PATHS=()
while :; do
if [ -f "\${_pvh_d}/.python-version" ] || [ -L "\${_pvh_d}/.python-version" ]; then
_PYENV_VH_PATHS+=("\${_pvh_d}/.python-version")
if [ -f "\${_pvh_d}/.python-version" ]; then
_pvh_found_local=1
break
fi
else
_PYENV_VH_PATHS+=("\${_pvh_d}")
fi
[ "\${_pvh_d}" = "/" ] && break
_pvh_d="\${_pvh_d%/*}"
[ -z "\${_pvh_d}" ] && _pvh_d="/"
done
if [ "\${_pvh_found_local}" = "0" ]; then
_PYENV_VH_PATHS+=("\${PYENV_ROOT}/version")
fi
_PYENV_VH_MTIMES="\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)"
return \$ret return \$ret
}; };
typeset -g -a precmd_functions typeset -g -a precmd_functions
@ -110,3 +206,13 @@ if [[ -z \$precmd_functions[(r)_pyenv_virtualenv_hook] ]]; then
fi fi
EOS EOS
} }
@test "outputs other shells syntax" {
export PYENV_VIRTUALENV_ROOT="${TMP}/pyenv/plugins/pyenv-virtualenv"
run pyenv-virtualenv-init - some_other_sh
assert_success
assert_output <<EOS
export PATH="${TMP}/pyenv/plugins/pyenv-virtualenv/shims:\${PATH}";
export PYENV_VIRTUALENV_INIT=1;
EOS
}

View file

@ -26,15 +26,16 @@ unstub_pyenv() {
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python3.5 -m venv --help : true" stub pyenv-exec "python -m venv --help : true"
stub pyenv-exec "python3.5 -m venv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";mkdir -p \${PYENV_ROOT}/versions/3.5.1/envs/venv/bin" stub pyenv-exec "python -m venv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";mkdir -p \${PYENV_ROOT}/versions/3.5.1/envs/venv/bin"
stub pyenv-exec "python -s -m ensurepip : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";touch \${PYENV_ROOT}/versions/3.5.1/envs/venv/bin/pip" stub pyenv-exec "python -s -m ensurepip : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";touch \${PYENV_ROOT}/versions/3.5.1/envs/venv/bin/pip"
run pyenv-virtualenv venv run pyenv-virtualenv venv
assert_success assert_success
assert_output <<OUT assert_output <<OUT
PYENV_VERSION=3.5.1 python3.5 -m venv ${PYENV_ROOT}/versions/3.5.1/envs/venv PYENV_VERSION=3.5.1 python -m venv ${TMP}/pyenv/versions/3.5.1/envs/venv
PYENV_VERSION=3.5.1/envs/venv python -s -m ensurepip PYENV_VERSION=3.5.1/envs/venv python -s -m ensurepip
rehashed rehashed
OUT OUT
@ -52,8 +53,8 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python3.3 -m venv --help : true" stub pyenv-exec "python -m venv --help : true"
stub pyenv-exec "python3.3 -m venv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";mkdir -p \${PYENV_ROOT}/versions/3.3.6/envs/venv/bin" stub pyenv-exec "python -m venv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";mkdir -p \${PYENV_ROOT}/versions/3.3.6/envs/venv/bin"
stub pyenv-exec "python -s -m ensurepip : false" stub pyenv-exec "python -s -m ensurepip : false"
stub pyenv-exec "python -s */get-pip.py : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";touch \${PYENV_ROOT}/versions/3.3.6/envs/venv/bin/pip" stub pyenv-exec "python -s */get-pip.py : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\";touch \${PYENV_ROOT}/versions/3.3.6/envs/venv/bin/pip"
stub curl true stub curl true
@ -62,7 +63,7 @@ OUT
assert_success assert_success
assert_output <<OUT assert_output <<OUT
PYENV_VERSION=3.3.6 python3.3 -m venv ${PYENV_ROOT}/versions/3.3.6/envs/venv PYENV_VERSION=3.3.6 python -m venv ${PYENV_ROOT}/versions/3.3.6/envs/venv
Installing pip from https://bootstrap.pypa.io/pip/3.3/get-pip.py... Installing pip from https://bootstrap.pypa.io/pip/3.3/get-pip.py...
PYENV_VERSION=3.3.6/envs/venv python -s ${TMP}/pyenv/cache/get-pip.py PYENV_VERSION=3.3.6/envs/venv python -s ${TMP}/pyenv/cache/get-pip.py
rehashed rehashed

View file

@ -12,10 +12,6 @@ create_version() {
chmod +x "${PYENV_ROOT}/versions/$1/bin/python" chmod +x "${PYENV_ROOT}/versions/$1/bin/python"
} }
remove_version() {
rm -fr "${PYENV_ROOT}/versions/$1"
}
create_virtualenv() { create_virtualenv() {
create_version "$1" create_version "$1"
create_version "${2:-$1}" create_version "${2:-$1}"
@ -40,11 +36,6 @@ create_virtualenv_pypy() {
touch "${PYENV_ROOT}/versions/$1/bin/activate" touch "${PYENV_ROOT}/versions/$1/bin/activate"
} }
remove_virtualenv() {
remove_version "$1"
remove_version "${2:-$1}"
}
create_m_venv() { create_m_venv() {
create_version "$1" create_version "$1"
create_version "${2:-$1}" create_version "${2:-$1}"
@ -52,10 +43,6 @@ create_m_venv() {
touch "${PYENV_ROOT}/versions/$1/bin/activate" touch "${PYENV_ROOT}/versions/$1/bin/activate"
} }
remove_m_venv() {
remove_version "${2:-$1}"
}
create_conda() { create_conda() {
create_version "$1" create_version "$1"
create_version "${2:-$1}" create_version "${2:-$1}"
@ -66,13 +53,8 @@ create_conda() {
touch "${PYENV_ROOT}/versions/${2:-$1}/bin/activate" touch "${PYENV_ROOT}/versions/${2:-$1}/bin/activate"
} }
remove_conda() {
remove_version "${2:-$1}"
}
@test "display prefix of virtualenv created by virtualenv" { @test "display prefix of virtualenv created by virtualenv" {
stub pyenv-version-name "echo foo" stub pyenv-version-name "echo foo"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\""
create_virtualenv "foo" "2.7.11" create_virtualenv "foo" "2.7.11"
PYENV_VERSION="foo" run pyenv-virtualenv-prefix PYENV_VERSION="foo" run pyenv-virtualenv-prefix
@ -83,13 +65,10 @@ ${PYENV_ROOT}/versions/2.7.11
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_virtualenv "foo" "2.7.11"
} }
@test "display prefix of virtualenv created by virtualenv (pypy)" { @test "display prefix of virtualenv created by virtualenv (pypy)" {
stub pyenv-version-name "echo foo" stub pyenv-version-name "echo foo"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\""
create_virtualenv_pypy "foo" "pypy-4.0.1" create_virtualenv_pypy "foo" "pypy-4.0.1"
PYENV_VERSION="foo" run pyenv-virtualenv-prefix PYENV_VERSION="foo" run pyenv-virtualenv-prefix
@ -100,13 +79,10 @@ ${PYENV_ROOT}/versions/pypy-4.0.1
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_virtualenv "foo" "pypy-4.0.1"
} }
@test "display prefix of virtualenv created by virtualenv (jython)" { @test "display prefix of virtualenv created by virtualenv (jython)" {
stub pyenv-version-name "echo foo" stub pyenv-version-name "echo foo"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\""
create_virtualenv_jython "foo" "jython-2.7.0" create_virtualenv_jython "foo" "jython-2.7.0"
PYENV_VERSION="foo" run pyenv-virtualenv-prefix PYENV_VERSION="foo" run pyenv-virtualenv-prefix
@ -117,14 +93,10 @@ ${PYENV_ROOT}/versions/jython-2.7.0
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_virtualenv "foo" "jython-2.7.0"
} }
@test "display prefixes of virtualenv created by virtualenv" { @test "display prefixes of virtualenv created by virtualenv" {
stub pyenv-version-name "echo foo:bar" stub pyenv-version-name "echo foo:bar"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\"" \
"bar : echo \"${PYENV_ROOT}/versions/bar\""
create_virtualenv "foo" "2.7.11" create_virtualenv "foo" "2.7.11"
create_virtualenv "bar" "3.5.1" create_virtualenv "bar" "3.5.1"
@ -136,14 +108,10 @@ ${PYENV_ROOT}/versions/2.7.11:${PYENV_ROOT}/versions/3.5.1
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_virtualenv "foo" "2.7.11"
remove_virtualenv "bar" "3.5.1"
} }
@test "display prefix of virtualenv created by venv" { @test "display prefix of virtualenv created by venv" {
stub pyenv-version-name "echo foo" stub pyenv-version-name "echo foo"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\""
create_m_venv "foo" "3.3.6" create_m_venv "foo" "3.3.6"
PYENV_VERSION="foo" run pyenv-virtualenv-prefix PYENV_VERSION="foo" run pyenv-virtualenv-prefix
@ -154,14 +122,10 @@ ${PYENV_ROOT}/versions/3.3.6
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_m_venv "foo" "3.3.6"
} }
@test "display prefixes of virtualenv created by venv" { @test "display prefixes of virtualenv created by venv" {
stub pyenv-version-name "echo foo:bar" stub pyenv-version-name "echo foo:bar"
stub pyenv-prefix "foo : echo \"${PYENV_ROOT}/versions/foo\"" \
"bar : echo \"${PYENV_ROOT}/versions/bar\""
create_m_venv "foo" "3.3.6" create_m_venv "foo" "3.3.6"
create_m_venv "bar" "3.4.4" create_m_venv "bar" "3.4.4"
@ -173,14 +137,10 @@ ${PYENV_ROOT}/versions/3.3.6:${PYENV_ROOT}/versions/3.4.4
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_m_venv "foo" "3.3.6"
remove_m_venv "bar" "3.4.4"
} }
@test "display prefix of virtualenv created by conda" { @test "display prefix of virtualenv created by conda" {
stub pyenv-version-name "echo miniconda3-3.16.0/envs/foo" stub pyenv-version-name "echo miniconda3-3.16.0/envs/foo"
stub pyenv-prefix "miniconda3-3.16.0/envs/foo : echo \"${PYENV_ROOT}/versions/miniconda3-3.16.0/envs/foo\""
create_conda "miniconda3-3.16.0/envs/foo" "miniconda3-3.16.0" create_conda "miniconda3-3.16.0/envs/foo" "miniconda3-3.16.0"
PYENV_VERSION="miniconda3-3.16.0/envs/foo" run pyenv-virtualenv-prefix PYENV_VERSION="miniconda3-3.16.0/envs/foo" run pyenv-virtualenv-prefix
@ -191,8 +151,6 @@ ${PYENV_ROOT}/versions/miniconda3-3.16.0/envs/foo
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_conda "miniconda3-3.16.0/envs/foo" "miniconda3-3.16.0"
} }
@test "should fail if the version is the system" { @test "should fail if the version is the system" {
@ -210,7 +168,6 @@ OUT
@test "should fail if the version is not a virtualenv" { @test "should fail if the version is not a virtualenv" {
stub pyenv-version-name "echo 3.4.4" stub pyenv-version-name "echo 3.4.4"
stub pyenv-prefix "3.4.4 : echo \"${PYENV_ROOT}/versions/3.4.4\""
create_version "3.4.4" create_version "3.4.4"
PYENV_VERSION="3.4.4" run pyenv-virtualenv-prefix PYENV_VERSION="3.4.4" run pyenv-virtualenv-prefix
@ -221,14 +178,10 @@ pyenv-virtualenv: version \`3.4.4' is not a virtualenv
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_version "3.4.4"
} }
@test "should fail if one of the versions is not a virtualenv" { @test "should fail if one of the versions is not a virtualenv" {
stub pyenv-version-name "echo venv33:3.4.4" stub pyenv-version-name "echo venv33:3.4.4"
stub pyenv-prefix "venv33 : echo \"${PYENV_ROOT}/versions/venv33\"" \
"3.4.4 : echo \"${PYENV_ROOT}/versions/3.4.4\""
create_virtualenv "venv33" "3.3.6" create_virtualenv "venv33" "3.3.6"
create_version "3.4.4" create_version "3.4.4"
@ -240,7 +193,22 @@ pyenv-virtualenv: version \`3.4.4' is not a virtualenv
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-prefix
remove_virtualenv "venv33" "3.3.6"
remove_version "3.4.4"
} }
@test "resolves a version that is not an exact match" {
stub pyenv-version-name "echo 3"
create_version "3.4.4"
stub pyenv-prefix "3 : echo \"$PYENV_ROOT/versions/3.4.4\""
run pyenv-virtualenv-prefix
assert_failure
assert_output <<OUT
pyenv-virtualenv: version \`3' is not a virtualenv
OUT
unstub pyenv-version-name
unstub pyenv-prefix
}

View file

@ -14,6 +14,7 @@ setup() {
stub pyenv-rehash " : true" stub pyenv-rehash " : true"
stub pyenv-version-name "echo \${PYENV_VERSION}" stub pyenv-version-name "echo \${PYENV_VERSION}"
stub curl true stub curl true
stub python-build "echo python2.7"
} }
teardown() { teardown() {
@ -22,6 +23,7 @@ teardown() {
unstub pyenv-prefix unstub pyenv-prefix
unstub pyenv-hooks unstub pyenv-hooks
unstub pyenv-rehash unstub pyenv-rehash
unstub python-build
teardown_version "2.7.8" teardown_version "2.7.8"
rm -fr "$TMP"/* rm -fr "$TMP"/*
} }
@ -31,8 +33,6 @@ teardown() {
create_executable "2.7.8" "python2.7" create_executable "2.7.8" "python2.7"
remove_executable "2.7.9" "python2.7" remove_executable "2.7.9" "python2.7"
stub pyenv-exec "python2.7 -m venv --help : false"
stub pyenv-exec "python2 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "virtualenv --verbose * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv --verbose * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : true" stub pyenv-exec "python -s -m ensurepip : true"
@ -40,13 +40,13 @@ teardown() {
run pyenv-virtualenv --verbose --python=python2.7 venv run pyenv-virtualenv --verbose --python=python2.7 venv
unstub pyenv-exec
assert_output <<OUT assert_output <<OUT
PYENV_VERSION=2.7.8 virtualenv --verbose --python=${PYENV_ROOT}/versions/2.7.8/bin/python2.7 ${PYENV_ROOT}/versions/2.7.8/envs/venv PYENV_VERSION=2.7.8 virtualenv --verbose --python=${PYENV_ROOT}/versions/2.7.8/bin/python2.7 ${PYENV_ROOT}/versions/2.7.8/envs/venv
OUT OUT
assert_success assert_success
unstub pyenv-which unstub pyenv-which
unstub pyenv-exec
remove_executable "2.7.7" "python2.7" remove_executable "2.7.7" "python2.7"
remove_executable "2.7.8" "python2.7" remove_executable "2.7.8" "python2.7"
@ -58,8 +58,6 @@ OUT
remove_executable "2.7.8" "python2.7" remove_executable "2.7.8" "python2.7"
create_executable "2.7.9" "python2.7" create_executable "2.7.9" "python2.7"
stub pyenv-exec "python2.7 -m venv --help : false"
stub pyenv-exec "python2 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "virtualenv --verbose * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv --verbose * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : true" stub pyenv-exec "python -s -m ensurepip : true"
@ -96,6 +94,7 @@ OUT
assert_output <<OUT assert_output <<OUT
pyenv-virtualenv: \`python2.7' is not installed in pyenv. pyenv-virtualenv: \`python2.7' is not installed in pyenv.
Run \`pyenv install python2.7' to install it.
OUT OUT
assert_failure assert_failure
@ -106,3 +105,13 @@ OUT
remove_executable "2.7.8" "python2.7" remove_executable "2.7.8" "python2.7"
remove_executable "2.7.9" "python2.7" remove_executable "2.7.9" "python2.7"
} }
@test "invalid python name" {
run pyenv-virtualenv --verbose --python=99.99.99 venv
assert_output <<OUT
pyenv-virtualenv: \`99.99.99' is not installed in pyenv.
It does not look like a valid Python version. See \`pyenv install --list' for available versions.
OUT
assert_failure
}

View file

@ -26,14 +26,14 @@ unstub_pyenv() {
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python3.5 -m venv --help : true" stub pyenv-exec "python -m venv --help : true"
stub pyenv-exec "python3.5 -m venv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "python -m venv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : true" stub pyenv-exec "python -s -m ensurepip : true"
run pyenv-virtualenv venv run pyenv-virtualenv venv
assert_output <<OUT assert_output <<OUT
PYENV_VERSION=3.5.1 python3.5 -m venv ${PYENV_ROOT}/versions/3.5.1/envs/venv PYENV_VERSION=3.5.1 python -m venv ${PYENV_ROOT}/versions/3.5.1/envs/venv
rehashed rehashed
OUT OUT
assert [ -x "${PYENV_ROOT}/versions/3.5.1/envs/venv/bin/pydoc" ] assert [ -x "${PYENV_ROOT}/versions/3.5.1/envs/venv/bin/pydoc" ]
@ -52,7 +52,7 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python3.5 -m venv --help : true" stub pyenv-exec "python -m venv --help : true"
stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : true" stub pyenv-exec "python -s -m ensurepip : true"
@ -77,8 +77,6 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python3.2 -m venv --help : false"
stub pyenv-exec "python3 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "pip install virtualenv* : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "pip install virtualenv* : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
@ -105,7 +103,7 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python3.5 -m venv --help : true" stub pyenv-exec "python -m venv --help : true"
stub pyenv-exec "pip install virtualenv : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "pip install virtualenv : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : true" stub pyenv-exec "python -s -m ensurepip : true"
@ -132,7 +130,7 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python3.5 -m venv --help : true" stub pyenv-exec "python -m venv --help : true"
stub pyenv-exec "pip install virtualenv : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "pip install virtualenv : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : true" stub pyenv-exec "python -s -m ensurepip : true"
@ -159,8 +157,6 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'" stub pyenv-prefix " : echo '${PYENV_ROOT}/versions/${PYENV_VERSION}'"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python3.2 -m venv --help : false"
stub pyenv-exec "python3 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "pip install virtualenv* : echo PIP_REQUIRE_VENV=\${PIP_REQUIRE_VENV} PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "pip install virtualenv* : echo PIP_REQUIRE_VENV=\${PIP_REQUIRE_VENV} PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "virtualenv * : echo PIP_REQUIRE_VENV=\${PIP_REQUIRE_VENV} PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PIP_REQUIRE_VENV=\${PIP_REQUIRE_VENV} PYENV_VERSION=\${PYENV_VERSION} \"\$@\""

View file

@ -1,4 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
export PS4='+($$:${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
set -e set -e
status=0 status=0
@ -6,41 +7,158 @@ program="${0##*/}"
PROGRAM="$(echo "$program" | tr a-z- A-Z_)" PROGRAM="$(echo "$program" | tr a-z- A-Z_)"
[ -n "$TMPDIR" ] || TMPDIR="/tmp" [ -n "$TMPDIR" ] || TMPDIR="/tmp"
_STUB_PLAN="${PROGRAM}_STUB_PLAN" STUB_PLAN="${PROGRAM}_STUB_PLAN"
_STUB_RUN="${PROGRAM}_STUB_RUN" STUB_PLAN="${!STUB_PLAN}"
_STUB_INDEX="${PROGRAM}_STUB_INDEX"
_STUB_RESULT="${PROGRAM}_STUB_RESULT"
_STUB_END="${PROGRAM}_STUB_END"
_STUB_DEBUG="${PROGRAM}_STUB_DEBUG"
if [ -n "${!_STUB_DEBUG}" ]; then STUB_RUN="${PROGRAM}_STUB_RUN"
echo "$program" "$@" >&${!_STUB_DEBUG} STUB_RUN="${!STUB_RUN:-${TMPDIR}/${program}-stub-run}"
fi STUB_INDEX=
STUB_RESULT=
[ -e "${!_STUB_PLAN}" ] || exit 1 STUB_END="${PROGRAM}_STUB_END"
[ -n "${!_STUB_RUN}" ] || eval "${_STUB_RUN}"="${TMPDIR}/${program}-stub-run" STUB_END="${!STUB_END}"
STUB_LOG="${PROGRAM}_STUB_LOG"
STUB_LOG="${!STUB_LOG:-${TMPDIR}/${program}-stub-log}"
STUB_LOCKFILE="${TMPDIR}/${program}-stub.lock"
release_lock() {
rm -f "$STUB_LOCKFILE"
trap - EXIT
}
acquire_lock() {
local start=$SECONDS
local acquire_timeout=10
local acquired=
while (( SECONDS <= start + $acquire_timeout )); do
( set -o noclobber; echo -n >"$STUB_LOCKFILE" ) 2>/dev/null && acquired=1
if [[ -n $acquired ]]; then
trap release_lock EXIT
break
else
# POSIX sleep(1) doesn't provide subsecond precision, but many others do
sleep 0.1 2>/dev/null || sleep 1
fi
done
if [[ -z $acquired ]]; then
echo "$0: error: could not acquire stub lock \`$STUB_LOCKFILE' in ${acquire_timeout} seconds" >&2
exit 2
fi
}
acquire_lock
if [[ -z $STUB_END ]]; then echo "$program" "$@" >>"$STUB_LOG"; fi
[[ -e $STUB_PLAN ]] || exit 1
# Initialize or load the stub run information. # Initialize or load the stub run information.
eval "${_STUB_INDEX}"=1 read_runfile() {
eval "${_STUB_RESULT}"=0 if [[ -e $STUB_RUN ]]; then source "$STUB_RUN"; fi
[ ! -e "${!_STUB_RUN}" ] || source "${!_STUB_RUN}" }
write_runfile() {
{
local i
echo "STUB_INDEX=$STUB_INDEX"
echo "STUB_RESULT=$STUB_RESULT"
echo "STUB_RUNCOUNTS=()"
for i in ${!STUB_RUNCOUNTS[@]}; do
echo "STUB_RUNCOUNTS[$i]=${STUB_RUNCOUNTS[$i]}"
done
} > "$STUB_RUN"
}
update_runfile_index() {
( STUB_INDEX=$((STUB_INDEX + 1))
write_runfile
)
}
update_runfile_result() {
(
# Another stubs may have run while we were running payload
# So we need to merge possible state changes
local our_result="$STUB_RESULT"
local -a our_runcounts
array_copy STUB_RUNCOUNTS our_runcounts
read_runfile
# merge our match_result and their match_result, with failure taking precedence
STUB_RESULT=$(( our_result | STUB_RESULT ))
# 3-way merge STUB_RUNCOUNTS (their changes),
# our_runcounts (our changes) and initial_runcounts (base)
local i
for i in $(printf '%s\n' ${!STUB_RUNCOUNTS[@]} ${!our_runcounts[@]} | sort -u); do
STUB_RUNCOUNTS[$i]=$((STUB_RUNCOUNTS[i] + our_runcounts[i] - initial_runcounts[i]))
done
write_runfile
)
}
array_copy() {
#`declare -p' is supposed to produce "declare -a src=([index]="value" <etc>)"
local data="$(declare -p ${1:?})"
local dest="${2:?}"
# Bash 5 dumps empty arrays as "declare -a arr"
if [[ $data != *=* ]]; then
data="()";
else
data="${data#*=}"
fi
# Bash 3 and MacPorts version of Bash 5 dump arrays in single quotes "declare -a arr='()'"
# but arr='(<value>)' createss "([0]='<value>')" rather than duplicate the array
if [[ ${data:0:1} == "'" && ${data:${#data}-1:1} == "'" ]]; then
data="${data:1:${#data}-2}"
fi
eval "$dest=$data"
}
# Loop over each line in the plan. STUB_INDEX=1
index=0 STUB_RESULT=0
while IFS= read -r line; do declare -a STUB_RUNCOUNTS
index=$(($index + 1)) read_runfile
declare -a initial_runcounts
if [ -z "${!_STUB_END}" ] && [ $index -eq "${!_STUB_INDEX}" ]; then array_copy STUB_RUNCOUNTS initial_runcounts
# We found the plan line we're interested in.
# Start off by assuming success.
result=0
# ${PROGRAM}_STUB_END envvar is set externally to trigger verification mode for `unstub'
# Execution mode
if [[ -z $STUB_END ]]; then
# Loop over each line in the plan.
regular_command_index=0
no_order_command_index=0
match_result=1
while IFS= read -r line; do
line_flags="${line%% *}"
line="${line#${line_flags} }"
line_flag_no_order="$(if [[ $line_flags == N ]]; then echo 1; fi)"
line_flag_multiple="$(if [[ $line_flags == M ]]; then echo 1; fi)"
line_flag_regular="$(if [[ $line_flags == - ]]; then echo 1; fi)"
unset line_flags
# Go through the plan until a match is found.
# For regular commands, only check the next command by index.
# Also keep track of no-order commands for the purpose of run count tracking
if [[ -n $line_flag_regular ]]; then
regular_command_index=$(($regular_command_index + 1))
if [[ $regular_command_index -ne $STUB_INDEX ]]; then
continue;
fi
else
no_order_command_index=$(($no_order_command_index + 1))
fi
# Split the line into an array of arguments to # Split the line into an array of arguments to
# match and a command to run to produce output. # match and a command to run to produce output.
command=" $line" command=" $line"
if [ "$command" != "${command/ : }" ]; then if [[ $command == *" : "* ]]; then
patterns="${command%% : *}" patterns="${command%% : *}"
command="${command#* : }" command="${command#* : }"
fi fi
@ -55,55 +173,110 @@ while IFS= read -r line; do
# Match the expected argument patterns to actual # Match the expected argument patterns to actual
# arguments. # arguments.
match_result=0
for (( i=0; i<${#patterns[@]}; i++ )); do for (( i=0; i<${#patterns[@]}; i++ )); do
pattern="${patterns[$i]}" pattern="${patterns[$i]}"
argument="${arguments[$i]}" argument="${arguments[$i]}"
case "$argument" in case "$argument" in
$pattern ) ;; $pattern ) ;;
* ) result=1 ;; * ) match_result=1 ;;
esac esac
done done
# If the arguments matched, evaluate the command # If the arguments matched, evaluate the command
# in a subshell. Otherwise, log the failure. # in a subshell. Otherwise, log the failure.
if [ $result -eq 0 ] ; then if [ $match_result -eq 0 ] ; then
set +e
( eval "$command" ) # If this is a regular command, push the regular command index for the next stub invocation
status="$?" if [[ -n $line_flag_regular ]]; then
set -e update_runfile_index
else else
eval "${_STUB_RESULT}"=1 STUB_RUNCOUNTS[$no_order_command_index]=$((STUB_RUNCOUNTS[no_order_command_index]+1))
fi
# Release the lock while running the payload to allow another `stub'
# of the same program to run concurrently (e.g. in a pipeline).
release_lock
( eval "$command" ) && status="$?" || status="$?"
break
fi fi
done < "$STUB_PLAN"
#If we never matched anything, we failed.
if [[ $match_result -eq 1 ]]; then
STUB_RESULT=1
#This also means that we never released the lock
# before running the payload
else
acquire_lock
fi fi
done < "${!_STUB_PLAN}" # Write out the match_result information.
update_runfile_result
release_lock
if [ -n "${!_STUB_END}" ]; then
# Clean up the run file.
rm -f "${!_STUB_RUN}"
# If the number of lines in the plan is larger than
# the requested index, we failed.
if [ $index -ge "${!_STUB_INDEX}" ]; then
eval "${_STUB_RESULT}"=1
fi
# Return the result.
exit "${!_STUB_RESULT}"
else
# If the requested index is larger than the number
# of lines in the plan file, we failed.
if [ "${!_STUB_INDEX}" -gt $index ]; then
eval "${_STUB_RESULT}"=1
fi
# Write out the run information.
{ echo "${_STUB_INDEX}=$((${!_STUB_INDEX} + 1))"
echo "${_STUB_RESULT}=${!_STUB_RESULT}"
} > "${!_STUB_RUN}"
exit "$status" exit "$status"
fi fi
# Verification mode (`unstub')
if [[ -n $STUB_END ]]; then
# `unstub' is supposed to run after any stubs are finished
release_lock
# If the number of regular commands in the plan is larger than
# the final regular_command_index, we failed.
if [[ $(grep -Ee '^-' "$STUB_PLAN" | wc -l ) -ge $STUB_INDEX ]]; then
STUB_RESULT=1
fi
# If no-order commands weren't executed exactly once
# and multiple-times commands at least once, we failed.
no_order_command_index=0
while IFS= read -r line; do
line_flags="${line%% *}"
line="${line#${line_flags} }"
line_flag_no_order="$(if [[ $line_flags == N ]]; then echo 1; fi)"
line_flag_multiple="$(if [[ $line_flags == M ]]; then echo 1; fi)"
line_flag_regular="$(if [[ $line_flags == - ]]; then echo 1; fi)"
unset line_flags
if [[ -z $line_flag_regular ]]; then
continue
fi
no_order_command_index=$((no_order_command_index + 1))
if [[ ( -n $line_flag_no_order && \
(( STUB_RUNCOUNTS[no_order_command_index] != 1 )) ) \
|| \
( -n $line_flag_multiple && \
(( STUB_RUNCOUNTS[no_order_command_index] < 1 )) ) ]]
then
STUB_RESULT=1
fi
done < "$STUB_PLAN"
if [[ $STUB_RESULT -ne 0 ]]; then
{
echo "plan:"
cat "$STUB_PLAN" || true
echo "log:"
cat "$STUB_LOG" || true
} >&2
fi
# Clean up the run file.
rm -f "$STUB_RUN"
rm -f "$STUB_LOG"
# Return the run result.
exit "$STUB_RESULT"
fi

View file

@ -1,6 +1,15 @@
export TMP="$BATS_TEST_DIRNAME/tmp" export TMP="$BATS_TEST_DIRNAME/tmp"
PATH=/usr/bin:/usr/sbin:/bin/:/sbin # Detect stat format for mtime: GNU uses -c %Y, BSD uses -f %m
# Must match the detection in bin/pyenv-virtualenv-init
if stat -L -c %Y / >/dev/null 2>&1; then
_stat_fmt="-L -c %Y"
else
_stat_fmt="-L -f %m"
fi
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
PATH=/usr/bin:/usr/sbin:/bin:/sbin
PATH="$BATS_TEST_DIRNAME/../bin:$PATH" PATH="$BATS_TEST_DIRNAME/../bin:$PATH"
PATH="$TMP/bin:$PATH" PATH="$TMP/bin:$PATH"
export PATH export PATH
@ -10,19 +19,51 @@ teardown() {
} }
stub() { stub() {
local FLAG_NO_ORDER=
local FLAG_MULTIPLE=
while (($#)); do
case "$1" in
-N|--no-order)
FLAG_NO_ORDER=1
shift
;;
-M|--multiple)
FLAG_MULTIPLE=1
shift
;;
-*)
echo "stub: unrecognized switch: $arg" >$2
return 1
;;
*)
break
;;
esac
done
local FLAGS=-
if [[ -n $FLAG_MULTIPLE ]]; then
FLAGS=M
elif [[ -n $FLAG_NO_ORDER ]]; then
FLAGS=N
fi
local program="$1" local program="$1"
local prefix="$(echo "$program" | tr a-z- A-Z_)" local prefix="$(echo "$program" | tr a-z- A-Z_)"
shift shift
export "${prefix}_STUB_PLAN"="${TMP}/${program}-stub-plan" export "${prefix}_STUB_PLAN"="${TMP}/${program}-stub-plan"
export "${prefix}_STUB_RUN"="${TMP}/${program}-stub-run" export "${prefix}_STUB_RUN"="${TMP}/${program}-stub-run"
export "${prefix}_STUB_LOG"="${TMP}/${program}-stub-log"
export "${prefix}_STUB_END"= export "${prefix}_STUB_END"=
mkdir -p "${TMP}/bin" mkdir -p "${TMP}/bin"
ln -sf "${BATS_TEST_DIRNAME}/stubs/stub" "${TMP}/bin/${program}" ln -sf "${BATS_TEST_DIRNAME}/stubs/stub" "${TMP}/bin/${program}"
touch "${TMP}/${program}-stub-plan" touch "${TMP}/${program}-stub-plan"
for arg in "$@"; do printf "%s\n" "$arg" >> "${TMP}/${program}-stub-plan"; done for arg in "$@"; do
echo "$FLAGS" "$arg" >> "${TMP}/${program}-stub-plan"
done
} }
unstub() { unstub() {
@ -82,6 +123,16 @@ assert_equal() {
fi fi
} }
assert_equal_wildcards() {
if [[ $1 != $2 ]]; then
{ echo "expected:"
echo "$2"
echo "actual:"
echo "$1"
} | flunk
fi
}
assert_output() { assert_output() {
local expected local expected
if [ $# -eq 0 ]; then expected="$(cat -)" if [ $# -eq 0 ]; then expected="$(cat -)"
@ -90,6 +141,14 @@ assert_output() {
assert_equal "$expected" "$output" assert_equal "$expected" "$output"
} }
assert_output_wildcards() {
local expected
if [ $# -eq 0 ]; then expected="$(cat -)"
else expected="$1"
fi
assert_equal_wildcards "$output" "$expected"
}
assert_output_contains() { assert_output_contains() {
local expected="$1" local expected="$1"
echo "$output" | grep -F "$expected" >/dev/null || { echo "$output" | grep -F "$expected" >/dev/null || {
@ -170,3 +229,4 @@ setup_conda() {
teardown_conda() { teardown_conda() {
rm -fr "${PYENV_ROOT}/versions/$1" rm -fr "${PYENV_ROOT}/versions/$1"
} }

View file

@ -10,8 +10,6 @@ setup() {
setup_virtualenv "2.7.7" setup_virtualenv "2.7.7"
stub pyenv-prefix "echo '${PYENV_ROOT}/versions/2.7.7'" stub pyenv-prefix "echo '${PYENV_ROOT}/versions/2.7.7'"
stub pyenv-version-name "echo 2.7.7" stub pyenv-version-name "echo 2.7.7"
stub pyenv-exec "python2.7 -m venv --help : false"
stub pyenv-exec "python2 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "virtualenv --version : echo \"1.11\"" stub pyenv-exec "virtualenv --version : echo \"1.11\""
@ -29,12 +27,12 @@ setup() {
setup_m_venv "3.4.1" setup_m_venv "3.4.1"
stub pyenv-version-name "echo 3.4.1" stub pyenv-version-name "echo 3.4.1"
stub pyenv-prefix "echo '${PYENV_ROOT}/versions/3.4.1'" stub pyenv-prefix "echo '${PYENV_ROOT}/versions/3.4.1'"
stub pyenv-exec "python3.4 -m venv --help : true" stub pyenv-exec "python -m venv --help : true"
run pyenv-virtualenv --version run pyenv-virtualenv --version
assert_success assert_success
[[ "$output" == "pyenv-virtualenv "?.?.?" (python3.4 -m venv)" ]] [[ "$output" == "pyenv-virtualenv "?.?.?" (python -m venv)" ]]
unstub pyenv-prefix unstub pyenv-prefix
teardown_m_venv "3.4.1" teardown_m_venv "3.4.1"

View file

@ -26,13 +26,14 @@ unstub_pyenv() {
export PYENV_VERSION="2.7.11" export PYENV_VERSION="2.7.11"
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python2.7 -m venv --help : false"
stub pyenv-exec "python2 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"; mkdir -p \"\$2/bin\""
stub pyenv-exec "python -s -m ensurepip : false" stub pyenv-exec "python -s -m ensurepip : false"
stub pyenv-exec "python -s */get-pip.py : true" stub pyenv-exec "python -s */get-pip.py : true"
stub curl true stub curl true
create_executable "${PYENV_VERSION}" "python-config"
create_executable "${PYENV_VERSION}" "python2-config"
create_executable "${PYENV_VERSION}" "python2.7-config"
run pyenv-virtualenv "2.7.11" "venv" run pyenv-virtualenv "2.7.11" "venv"
@ -41,8 +42,10 @@ PYENV_VERSION=2.7.11 virtualenv ${PYENV_ROOT}/versions/2.7.11/envs/venv
Installing pip from https://bootstrap.pypa.io/pip/2.7/get-pip.py... Installing pip from https://bootstrap.pypa.io/pip/2.7/get-pip.py...
rehashed rehashed
OUT OUT
assert [ -x "${PYENV_ROOT}/versions/2.7.11/envs/venv/bin/pydoc" ]
assert_success assert_success
for x in pydoc python-config python2-config python2.7-config; do
assert [ -x "${PYENV_ROOT}/versions/2.7.11/envs/venv/bin/$x" ]
done
unstub_pyenv unstub_pyenv
unstub pyenv-virtualenv-prefix unstub pyenv-virtualenv-prefix
@ -53,14 +56,12 @@ OUT
@test "create virtualenv from a given prefix" { @test "create virtualenv from a given prefix" {
stub_pyenv "2.7.11" stub_pyenv "2.7.11"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python2.7 -m venv --help : false"
stub pyenv-exec "python2 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : false" stub pyenv-exec "python -s -m ensurepip : false"
stub pyenv-exec "python -s */get-pip.py : true" stub pyenv-exec "python -s */get-pip.py : true"
stub curl true stub curl true
stub pyenv-latest "-q 2.7 : echo 2.7.11" stub pyenv-latest "-f 2.7 : echo 2.7.11"
run pyenv-virtualenv "2.7" "venv" run pyenv-virtualenv "2.7" "venv"
@ -84,8 +85,6 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-version-name "echo \${PYENV_VERSION}" stub pyenv-version-name "echo \${PYENV_VERSION}"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python2.7 -m venv --help : false"
stub pyenv-exec "python2 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : false" stub pyenv-exec "python -s -m ensurepip : false"
@ -114,8 +113,6 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-version-name "echo \${PYENV_VERSION}" stub pyenv-version-name "echo \${PYENV_VERSION}"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python2.7 -m venv --help : false"
stub pyenv-exec "python2 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : false" stub pyenv-exec "python -s -m ensurepip : false"
@ -144,8 +141,6 @@ OUT
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-version-name "echo \${PYENV_VERSION}" stub pyenv-version-name "echo \${PYENV_VERSION}"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python2.7 -m venv --help : false"
stub pyenv-exec "python2 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : false" stub pyenv-exec "python -s -m ensurepip : false"
@ -209,8 +204,6 @@ OUT
export PYENV_VERSION="2.7.11" export PYENV_VERSION="2.7.11"
stub_pyenv "${PYENV_VERSION}" stub_pyenv "${PYENV_VERSION}"
stub pyenv-virtualenv-prefix " : false" stub pyenv-virtualenv-prefix " : false"
stub pyenv-exec "python2.7 -m venv --help : false"
stub pyenv-exec "python2 -m venv --help : false"
stub pyenv-exec "python -m venv --help : false" stub pyenv-exec "python -m venv --help : false"
stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\"" stub pyenv-exec "virtualenv * : echo PYENV_VERSION=\${PYENV_VERSION} \"\$@\""
stub pyenv-exec "python -s -m ensurepip : false" stub pyenv-exec "python -s -m ensurepip : false"

View file

@ -2,27 +2,79 @@
load test_helper load test_helper
setup() { create_m_system_venv() {
export PYENV_ROOT="${TMP}/pyenv" # Create a mock virtual environment in the same way a venv created from
mkdir -p "${PYENV_ROOT}/versions/2.7.6" # the system Python version looks.
mkdir -p "${PYENV_ROOT}/versions/3.3.3" #
mkdir -p "${PYENV_ROOT}/versions/venv27" # The venv is in ${PYENV_ROOT}/versions, is not a symlink, and
mkdir -p "${PYENV_ROOT}/versions/venv33" # home is /usr/bin in the pyenv.cfg.
create_executable "$2" "python"
create_executable "$2" "activate"
local version="$1"
local venv="$2"
local venv_dir="${PYENV_ROOT}/versions/${venv}"
echo "home = /usr/bin" > "${venv_dir}/pyvenv.cfg"
} }
@test "list virtual environments only" {
stub pyenv-version-name ": echo system" create_m_venv() {
stub pyenv-virtualenv-prefix "2.7.6 : false" # Create a mock virtual environment from an installed (not system) Python version.
stub pyenv-virtualenv-prefix "3.3.3 : false" #
stub pyenv-virtualenv-prefix "venv27 : echo \"${PYENV_ROOT}/versions/2.7.6\"" # The venv name is a symlink inside ${PYENV_ROOT}/versions that points to
stub pyenv-virtualenv-prefix "venv33 : echo \"${PYENV_ROOT}/versions/3.3.3\"" # the real venv directory inside the Python version used to created and
# home points to the bin directory inside the venv dir.
setup_m_venv "$1/envs/$2"
local version="$1"
local venv="$2"
local venv_dir="${PYENV_ROOT}/versions/${version}/envs/${venv}"
echo "home = ${PYENV_ROOT}/versions/${version}/bin" > "${venv_dir}/pyvenv.cfg"
ln -sf "${venv_dir}" "${PYENV_ROOT}/versions/${venv}"
}
setup() {
export PYENV_ROOT="${TMP}/pyenv"
}
@test "system venv" {
stub pyenv-version-name ": echo venv314"
stub pyenv-version-origin ": echo PYENV_VERSION"
create_m_venv "3.14.3" "venv314"
create_m_system_venv "3.9.11" "system_venv"
run pyenv-virtualenvs run pyenv-virtualenvs
assert_success assert_success
assert_output <<OUT assert_output <<OUT
venv27 (created from ${PYENV_ROOT}/versions/2.7.6) 3.14.3/envs/venv314 (created from ${PYENV_ROOT}/versions/3.14.3)
venv33 (created from ${PYENV_ROOT}/versions/3.3.3) system_venv (created from /usr)
* venv314 --> ${PYENV_ROOT}/versions/3.14.3/envs/venv314 (set by PYENV_VERSION)
OUT
unstub pyenv-version-name
unstub pyenv-version-origin
}
@test "list virtual environments" {
stub pyenv-version-name ": echo system"
stub pyenv-virtualenv-prefix "2.7.6/envs/venv27 : echo \"${PYENV_ROOT}/versions/2.7.6\""
stub pyenv-virtualenv-prefix "3.3.3/envs/venv33 : echo \"${PYENV_ROOT}/versions/3.3.3\""
create_m_venv "2.7.6" "venv27"
create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs
assert_success
assert_output <<OUT
2.7.6/envs/venv27 (created from ${PYENV_ROOT}/versions/2.7.6)
3.3.3/envs/venv33 (created from ${PYENV_ROOT}/versions/3.3.3)
venv27 --> ${PYENV_ROOT}/versions/2.7.6/envs/venv27
venv33 --> ${PYENV_ROOT}/versions/3.3.3/envs/venv33
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
@ -30,37 +82,101 @@ OUT
} }
@test "list virtual environments with hit prefix" { @test "list virtual environments with hit prefix" {
stub pyenv-version-name ": echo venv33" stub pyenv-version-name ": echo 3.3.3/envs/venv33"
stub pyenv-virtualenv-prefix "2.7.6 : false" stub pyenv-version-origin ": echo PYENV_VERSION"
stub pyenv-virtualenv-prefix "3.3.3 : false"
stub pyenv-virtualenv-prefix "venv27 : echo \"/usr\"" create_m_venv "2.7.6" "venv27"
stub pyenv-virtualenv-prefix "venv33 : echo \"/usr\"" create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs run pyenv-virtualenvs
assert_success assert_success
assert_output <<OUT assert_output <<OUT
venv27 (created from /usr) 2.7.6/envs/venv27 (created from ${PYENV_ROOT}/versions/2.7.6)
* venv33 (created from /usr) * 3.3.3/envs/venv33 (created from ${PYENV_ROOT}/versions/3.3.3) (set by PYENV_VERSION)
venv27 --> ${PYENV_ROOT}/versions/2.7.6/envs/venv27
venv33 --> ${PYENV_ROOT}/versions/3.3.3/envs/venv33
OUT OUT
unstub pyenv-version-name unstub pyenv-version-name
unstub pyenv-virtualenv-prefix unstub pyenv-version-origin
} }
@test "list virtual environments with --bare" { @test "list bare virtual environments" {
stub pyenv-virtualenv-prefix "2.7.6 : false" create_m_venv "2.7.6" "venv27"
stub pyenv-virtualenv-prefix "3.3.3 : false" create_m_venv "3.3.3" "venv33"
stub pyenv-virtualenv-prefix "venv27 : echo \"/usr\""
stub pyenv-virtualenv-prefix "venv33 : echo \"/usr\""
run pyenv-virtualenvs --bare run pyenv-virtualenvs --bare
assert_success assert_success
assert_output <<OUT assert_output <<OUT
2.7.6/envs/venv27
3.3.3/envs/venv33
venv27 venv27
venv33 venv33
OUT OUT
}
unstub pyenv-virtualenv-prefix
@test "list bare virtual environments without aliases" {
create_m_venv "2.7.6" "venv27"
create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs --bare --skip-aliases
assert_success
assert_output <<OUT
2.7.6/envs/venv27
3.3.3/envs/venv33
OUT
}
@test "list virtual environments without aliases" {
stub pyenv-version-name ": echo system"
create_m_venv "2.7.6" "venv27"
create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs --skip-aliases
assert_success
assert_output <<OUT
2.7.6/envs/venv27 (created from ${PYENV_ROOT}/versions/2.7.6)
3.3.3/envs/venv33 (created from ${PYENV_ROOT}/versions/3.3.3)
OUT
unstub pyenv-version-name
}
@test "hit prefix matches alias version name" {
stub pyenv-version-name ": echo venv27"
stub pyenv-version-origin ": echo PYENV_VERSION"
create_m_venv "2.7.6" "venv27"
create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs
assert_success
assert_output <<OUT
2.7.6/envs/venv27 (created from ${PYENV_ROOT}/versions/2.7.6)
3.3.3/envs/venv33 (created from ${PYENV_ROOT}/versions/3.3.3)
* venv27 --> ${PYENV_ROOT}/versions/2.7.6/envs/venv27 (set by PYENV_VERSION)
venv33 --> ${PYENV_ROOT}/versions/3.3.3/envs/venv33
OUT
unstub pyenv-version-name
unstub pyenv-version-origin
}
@test "completions output" {
create_m_venv "2.7.6" "venv27"
create_m_venv "3.3.3" "venv33"
run pyenv-virtualenvs --complete
assert_success
assert_output <<OUT
--bare
--skip-aliases
OUT
} }