mirror of
https://github.com/pyenv/pyenv.git
synced 2025-11-09 03:53:48 -05:00
Compare commits
195 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10e96bfc47 | ||
|
|
896e76c3d5 | ||
|
|
228fbf4c4f | ||
|
|
84839ae589 | ||
|
|
75aee988b3 | ||
|
|
1d08efe089 | ||
|
|
2e3ef01abb | ||
|
|
efeab7f8ee | ||
|
|
e5c7eb3399 | ||
|
|
a43095dc11 | ||
|
|
4aa904634f | ||
|
|
4a7d13d7ce | ||
|
|
c335ab83de | ||
|
|
bf1fcd346b | ||
|
|
873e0249a5 | ||
|
|
d6e547b94e | ||
|
|
3bac268cdb | ||
|
|
19fa774e42 | ||
|
|
af03af9593 | ||
|
|
1fcb988164 | ||
|
|
925e5ad0e7 | ||
|
|
35960ee19e | ||
|
|
c3ba994ec2 | ||
|
|
a3b98a4223 | ||
|
|
ac020225c2 | ||
|
|
f2ac882579 | ||
|
|
e8b7a27ee6 | ||
|
|
8d0ca21451 | ||
|
|
d7a5e87d75 | ||
|
|
5cae73944f | ||
|
|
325abac17d | ||
|
|
d10388a052 | ||
|
|
7c4350edf4 | ||
|
|
d6bb1c6396 | ||
|
|
ad6544409b | ||
|
|
ae8a0ee125 | ||
|
|
3646eb840b | ||
|
|
6e58140657 | ||
|
|
a7e508fcdf | ||
|
|
d1f1865c2a | ||
|
|
86b5797083 | ||
|
|
5d78e47399 | ||
|
|
59acc42647 | ||
|
|
4fec76f267 | ||
|
|
592fe6a087 | ||
|
|
906a6acc10 | ||
|
|
3112172081 | ||
|
|
cfe1c37d26 | ||
|
|
af9201ea1e | ||
|
|
56512aee3b | ||
|
|
e390b228c8 | ||
|
|
a632465cf4 | ||
|
|
54744db05e | ||
|
|
dd79c11f6c | ||
|
|
0704e65781 | ||
|
|
8644fb5519 | ||
|
|
41e242857e | ||
|
|
6f21f76965 | ||
|
|
8be1b9bd0e | ||
|
|
7eafc5fe02 | ||
|
|
9fe4cb8e1e | ||
|
|
61747c06d4 | ||
|
|
7509eafdd0 | ||
|
|
593f820a7d | ||
|
|
5c12600625 | ||
|
|
6717c62dc1 | ||
|
|
5f9c0ba613 | ||
|
|
52acbdf83f | ||
|
|
85f304ef3b | ||
|
|
41580b69db | ||
|
|
3e5347be1e | ||
|
|
172a79e993 | ||
|
|
8275e15cb0 | ||
|
|
90c0357682 | ||
|
|
30aaf4edba | ||
|
|
d97713d1b5 | ||
|
|
43e30ef815 | ||
|
|
6b1cc34610 | ||
|
|
d2d3012f17 | ||
|
|
410e05bf8c | ||
|
|
a6cf6aeadb | ||
|
|
8406a2bc7f | ||
|
|
ed1a3a5545 | ||
|
|
22ee5d4175 | ||
|
|
7c7c4dc11c | ||
|
|
45ae8d2ebc | ||
|
|
396e65a461 | ||
|
|
959968c46d | ||
|
|
009ef3a2db | ||
|
|
acdd8a95bd | ||
|
|
98412dba80 | ||
|
|
6426f852d0 | ||
|
|
33f8621ec8 | ||
|
|
9572edf4bb | ||
|
|
117a381575 | ||
|
|
56a440e4a7 | ||
|
|
a8ecfc743e | ||
|
|
c4395e5820 | ||
|
|
a54b47e783 | ||
|
|
c6cc0a1959 | ||
|
|
b39d4291be | ||
|
|
cec6d46792 | ||
|
|
e4f61e67e2 | ||
|
|
42aa760e2e | ||
|
|
d2c527cdd7 | ||
|
|
a76c4aaafa | ||
|
|
5b5c60fb6e | ||
|
|
304cb7b6a7 | ||
|
|
25fdc1caf9 | ||
|
|
264cb65a1e | ||
|
|
00d93c1d91 | ||
|
|
68fca03bb8 | ||
|
|
6cc7bff383 | ||
|
|
38e1fbb08e | ||
|
|
69323e77cc | ||
|
|
526f2de13d | ||
|
|
28cd6f123e | ||
|
|
d3d4606d2f | ||
|
|
0767d64344 | ||
|
|
76e64ff2ea | ||
|
|
b0fb351419 | ||
|
|
e7fd07dd91 | ||
|
|
faf999211b | ||
|
|
585ed84283 | ||
|
|
d061cb4651 | ||
|
|
059bb2c151 | ||
|
|
b904ea54cc | ||
|
|
dcba8b4064 | ||
|
|
633436706f | ||
|
|
4092eba274 | ||
|
|
064e1c48ba | ||
|
|
462bb67709 | ||
|
|
b424d452d0 | ||
|
|
80af359232 | ||
|
|
ccb4601f3a | ||
|
|
5d6f998c52 | ||
|
|
6b842a7670 | ||
|
|
45951d2cbb | ||
|
|
d604acb78a | ||
|
|
37405c3249 | ||
|
|
268c61a69c | ||
|
|
b5429624c2 | ||
|
|
5f7597e754 | ||
|
|
62d7798270 | ||
|
|
4086bbe562 | ||
|
|
60c9339685 | ||
|
|
d3f8de4c04 | ||
|
|
0843745be9 | ||
|
|
d4d69ed0cd | ||
|
|
0493a33f59 | ||
|
|
8bc71e9161 | ||
|
|
a5a1c4d50d | ||
|
|
c879cb0f2f | ||
|
|
59004d77ed | ||
|
|
c2cfbd1e8b | ||
|
|
a17c5fb596 | ||
|
|
c6324ff45a | ||
|
|
74c2486a2c | ||
|
|
ac5dce9014 | ||
|
|
19ae300eb8 | ||
|
|
e429cc0bd8 | ||
|
|
d58cf6ec71 | ||
|
|
143b2c9c02 | ||
|
|
f977248086 | ||
|
|
569d464d36 | ||
|
|
7795476af1 | ||
|
|
137e705db7 | ||
|
|
302797ba41 | ||
|
|
40db754168 | ||
|
|
5c3268c9af | ||
|
|
dd86f543fc | ||
|
|
c46a970595 | ||
|
|
8bb5b1607e | ||
|
|
cc9726c641 | ||
|
|
a574a74042 | ||
|
|
0c3967aa32 | ||
|
|
af454a32dc | ||
|
|
d38d18ec25 | ||
|
|
577f04653d | ||
|
|
8ebf088360 | ||
|
|
4e923221ce | ||
|
|
370c26a6c9 | ||
|
|
a3fa9b73b8 | ||
|
|
483e7f9bdf | ||
|
|
ae2e7a3f0b | ||
|
|
59785f6762 | ||
|
|
806f3f6ae2 | ||
|
|
1c772d5ff2 | ||
|
|
8103febc62 | ||
|
|
8b18b962a3 | ||
|
|
199e598351 | ||
|
|
e55e3c05eb | ||
|
|
bc1b66250f | ||
|
|
dfba9f7608 | ||
|
|
fb9130e85a |
@@ -1,4 +0,0 @@
|
|||||||
.git/
|
|
||||||
.python-version
|
|
||||||
.vscode/
|
|
||||||
.idea/
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Editor configuration, see https://editorconfig.org
|
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
end_of_line = lf
|
|
||||||
charset = utf-8
|
|
||||||
|
|
||||||
# Makefiles always use tabs for indentation
|
|
||||||
[Makefile]
|
|
||||||
indent_style = tab
|
|
||||||
indent_size = unset # Allow user-defined tab width
|
|
||||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/share/man/man[1-8]/*.[1-8] linguist-generated
|
||||||
12
.github/FUNDING.yml
vendored
12
.github/FUNDING.yml
vendored
@@ -1,12 +0,0 @@
|
|||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
github: [pyenv] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
|
||||||
patreon: # Replace with a single Patreon username
|
|
||||||
open_collective: pyenv # Replace with a single Open Collective username
|
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
|
||||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
||||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
||||||
liberapay: # Replace with a single Liberapay username
|
|
||||||
issuehunt: # Replace with a single IssueHunt username
|
|
||||||
otechie: # Replace with a single Otechie username
|
|
||||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
||||||
26
.github/ISSUE_TEMPLATE.md
vendored
26
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,26 +0,0 @@
|
|||||||
Too many issues will kill our team's development velocity, drastically.
|
|
||||||
Make sure you have checked all steps below.
|
|
||||||
|
|
||||||
### 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 issues](https://github.com/pyenv/pyenv/issues). You should look for closed issues, too.
|
|
||||||
* [ ] Make sure you are not asking us to help solving your specific issue.
|
|
||||||
* 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.
|
|
||||||
* [ ] 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.
|
|
||||||
* [ ] Make sure your problem is not derived from plugins.
|
|
||||||
* This repository is maintaining `pyenv` and the default `python-build` plugin only. Please refrain from reporting issues of other plugins here.
|
|
||||||
|
|
||||||
### Description
|
|
||||||
- [ ] Platform information (e.g. Ubuntu Linux 16.04):
|
|
||||||
- [ ] OS architecture (e.g. amd64):
|
|
||||||
- [ ] pyenv version:
|
|
||||||
- [ ] Python version:
|
|
||||||
- [ ] C Compiler information (e.g. gcc 7.3):
|
|
||||||
- [ ] Please attach the debug trace of the failing command as a gist:
|
|
||||||
* Run `env PYENV_DEBUG=1 <faulty command> 2>&1 | tee trace.log` and attach `trace.log`. E.g. if you have a problem with installing Python, run `env PYENV_DEBUG=1 pyenv install -v <version> 2>&1 | tee trace.log` (note the `-v` option to `pyenv install`).
|
|
||||||
- [ ] If you have a problem with installing Python, please also attach `config.log` from the build directory
|
|
||||||
* The build directory is reported after the "BUILD FAILED" message and is usually under `/tmp`.
|
|
||||||
- [ ] If the build succeeds but the problem is still with the build process (e.g. the resulting Python is missing a feature), please attach
|
|
||||||
* the debug trace from reinstalling the faulty version with `env PYENV_DEBUG=1 pyenv install -f -k -v <version> 2>&1 | tee trace.log`
|
|
||||||
* `config.log` from the build directory. When using `pyenv install` with `-k` as per above, the build directory will be under `$PYENV_ROOT/sources`.
|
|
||||||
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,16 +0,0 @@
|
|||||||
Make sure you have checked all steps below.
|
|
||||||
|
|
||||||
### Prerequisite
|
|
||||||
* [ ] Please consider implementing the feature as a hook script or plugin as a first step.
|
|
||||||
* pyenv has some powerful support for plugins and hook scripts. Please refer to [Authoring plugins](https://github.com/pyenv/pyenv/wiki/Authoring-plugins) for details and try to implement it as a plugin if possible.
|
|
||||||
* [ ] Please consider contributing the patch upstream to [rbenv](https://github.com/rbenv/rbenv), since we have borrowed most of the code from that project.
|
|
||||||
* We occasionally import the changes from rbenv. In general, you can expect changes made in rbenv will be imported to pyenv too, eventually.
|
|
||||||
* Generally speaking, we prefer not to make changes in the core in order to keep compatibility with rbenv.
|
|
||||||
* [ ] My PR addresses the following pyenv issue (if any)
|
|
||||||
- Closes https://github.com/pyenv/pyenv/issues/XXXX
|
|
||||||
|
|
||||||
### Description
|
|
||||||
- [ ] Here are some details about my PR
|
|
||||||
|
|
||||||
### Tests
|
|
||||||
- [ ] My PR adds the following unit tests (if any)
|
|
||||||
10
.github/dependabot.yml
vendored
10
.github/dependabot.yml
vendored
@@ -1,10 +1,6 @@
|
|||||||
version: 2
|
version: 2
|
||||||
updates:
|
updates:
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: 'github-actions'
|
||||||
directory: "/"
|
directory: '/'
|
||||||
schedule:
|
schedule:
|
||||||
interval: "monthly"
|
interval: 'weekly'
|
||||||
groups:
|
|
||||||
github-actions:
|
|
||||||
patterns:
|
|
||||||
- "*"
|
|
||||||
|
|||||||
17
.github/workflows/ci.yml
vendored
Normal file
17
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
name: CI
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install bats
|
||||||
|
run: git clone --depth 1 --branch v1.10.0 https://github.com/bats-core/bats-core.git bats
|
||||||
|
- name: Run tests
|
||||||
|
run: PATH="./bats/bin:$PATH" test/run
|
||||||
29
.github/workflows/lint.yml
vendored
Normal file
29
.github/workflows/lint.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
name: Lint
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
shellcheck:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Repository checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Differential ShellCheck
|
||||||
|
uses: redhat-plumbers-in-action/differential-shellcheck@v5
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
43
.github/workflows/macos_build.yml
vendored
43
.github/workflows/macos_build.yml
vendored
@@ -1,43 +0,0 @@
|
|||||||
name: macos_build
|
|
||||||
on: [pull_request, push]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read # to fetch code (actions/checkout)
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
macos_build:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
python-version:
|
|
||||||
- "3.8"
|
|
||||||
- "3.9"
|
|
||||||
- "3.10"
|
|
||||||
- "3.11"
|
|
||||||
- "3.12"
|
|
||||||
runs-on: macos-11
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# Normally, we would use the superbly maintained...
|
|
||||||
# - uses: actions/setup-python@v2
|
|
||||||
# with:
|
|
||||||
# python-version: ${{ matrix.python-version }}
|
|
||||||
# ... but in the repo, we want to test pyenv builds on macOS
|
|
||||||
- run: |
|
|
||||||
brew install openssl readline sqlite3 xz zlib
|
|
||||||
# https://github.com/pyenv/pyenv#installation
|
|
||||||
- run: pwd
|
|
||||||
- env:
|
|
||||||
PYENV_ROOT: /Users/runner/work/pyenv/pyenv
|
|
||||||
run: |
|
|
||||||
echo $PYENV_ROOT
|
|
||||||
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
|
|
||||||
bin/pyenv --debug install ${{ matrix.python-version }}
|
|
||||||
bin/pyenv global ${{ matrix.python-version }}
|
|
||||||
bin/pyenv rehash
|
|
||||||
- run: python --version
|
|
||||||
- run: python -m pip --version
|
|
||||||
- shell: python # Prove that actual Python == expected Python
|
|
||||||
env:
|
|
||||||
EXPECTED_PYTHON: ${{ matrix.python-version }}
|
|
||||||
run: import os, sys ; assert sys.version.startswith(os.getenv("EXPECTED_PYTHON"))
|
|
||||||
143
.github/workflows/modified_scripts_build.yml
vendored
143
.github/workflows/modified_scripts_build.yml
vendored
@@ -1,143 +0,0 @@
|
|||||||
name: modified_scripts
|
|
||||||
on: [pull_request]
|
|
||||||
jobs:
|
|
||||||
discover_modified_scripts:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
versions: ${{steps.modified-versions.outputs.versions}}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: git fetch origin "$GITHUB_BASE_REF"
|
|
||||||
- shell: bash
|
|
||||||
run: >
|
|
||||||
versions=$(git diff "origin/$GITHUB_BASE_REF" --name-only -z
|
|
||||||
| perl -ne 'BEGIN {$\="\n";$/="\0";} chomp;
|
|
||||||
if (/^plugins\/python-build\/share\/python-build\/(?:([^\/]+)|patches\/([^\/]+)\/.*)$/ and -e $& )
|
|
||||||
{ print $1.$2; }' \
|
|
||||||
| sort -u);
|
|
||||||
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64);
|
|
||||||
echo "versions<<$EOF" >> $GITHUB_ENV;
|
|
||||||
echo "$versions" >> $GITHUB_ENV;
|
|
||||||
echo "$EOF" >> $GITHUB_ENV;
|
|
||||||
- id: modified-versions
|
|
||||||
run: |
|
|
||||||
echo -n "::set-output name=versions::"
|
|
||||||
echo "${{ env.versions }}" | jq -R . | jq -sc .
|
|
||||||
macos_build:
|
|
||||||
needs: discover_modified_scripts
|
|
||||||
if: needs.discover_modified_scripts.outputs.versions != '[""]'
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
python-version: ${{fromJson(needs.discover_modified_scripts.outputs.versions)}}
|
|
||||||
os: ["macos-11", "macos-12"]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: |
|
|
||||||
#envvars
|
|
||||||
export PYENV_ROOT="$GITHUB_WORKSPACE"
|
|
||||||
echo "PYENV_ROOT=$PYENV_ROOT" >> $GITHUB_ENV
|
|
||||||
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
|
|
||||||
- run: |
|
|
||||||
#prerequisites
|
|
||||||
brew install openssl openssl@1.1 readline sqlite3 xz zlib
|
|
||||||
if [[ "${{ matrix.python-version }}" =~ pypy.*-(src|dev) ]]; then
|
|
||||||
export PYENV_BOOTSTRAP_VERSION=pypy2.7-7
|
|
||||||
echo "PYENV_BOOTSTRAP_VERSION=$PYENV_BOOTSTRAP_VERSION" >> $GITHUB_ENV
|
|
||||||
pyenv install $PYENV_BOOTSTRAP_VERSION
|
|
||||||
fi
|
|
||||||
- run: |
|
|
||||||
#build
|
|
||||||
pyenv --debug install ${{ matrix.python-version }}
|
|
||||||
pyenv global ${{ matrix.python-version }}
|
|
||||||
# Micropython doesn't support --version
|
|
||||||
- run: |
|
|
||||||
#print version
|
|
||||||
if [[ "${{ matrix.python-version }}" == "micropython-"* ]]; then
|
|
||||||
python -c 'import sys; print(sys.version)'
|
|
||||||
else
|
|
||||||
python --version
|
|
||||||
python -m pip --version
|
|
||||||
fi
|
|
||||||
# Micropython doesn't support sys.executable, os.path, older versions even os
|
|
||||||
- env:
|
|
||||||
EXPECTED_PYTHON: ${{ matrix.python-version }}
|
|
||||||
run: |
|
|
||||||
#check
|
|
||||||
if [[ "${{ matrix.python-version }}" == "micropython-"* ]]; then
|
|
||||||
[[ $(pyenv which python) == "${{ env.PYENV_ROOT }}/versions/${{ matrix.python-version }}/bin/python" ]] || exit 1
|
|
||||||
python -c 'import sys; assert sys.implementation.name == "micropython"'
|
|
||||||
else
|
|
||||||
python -c 'if True:
|
|
||||||
import os, sys, os.path
|
|
||||||
correct_dir = os.path.join(
|
|
||||||
os.environ["PYENV_ROOT"],
|
|
||||||
"versions",
|
|
||||||
os.environ["EXPECTED_PYTHON"],
|
|
||||||
"bin")
|
|
||||||
assert os.path.dirname(sys.executable) == correct_dir'
|
|
||||||
fi
|
|
||||||
# bundled executables in some Anaconda releases cause the post-run step to hang in MacOS
|
|
||||||
- run: |
|
|
||||||
pyenv global system
|
|
||||||
rm -f "$(pyenv root)"/shims/*
|
|
||||||
|
|
||||||
ubuntu_build:
|
|
||||||
needs: discover_modified_scripts
|
|
||||||
if: needs.discover_modified_scripts.outputs.versions != '[""]'
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
python-version: ${{fromJson(needs.discover_modified_scripts.outputs.versions)}}
|
|
||||||
os: ["ubuntu-20.04", "ubuntu-22.04"]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: |
|
|
||||||
#envvars
|
|
||||||
export PYENV_ROOT="$GITHUB_WORKSPACE"
|
|
||||||
echo "PYENV_ROOT=$PYENV_ROOT" >> $GITHUB_ENV
|
|
||||||
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
|
|
||||||
- run: |
|
|
||||||
#prerequisites
|
|
||||||
sudo apt-get update -q; sudo apt-get install -yq make build-essential \
|
|
||||||
libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
|
|
||||||
curl llvm libncurses5-dev libncursesw5-dev \
|
|
||||||
xz-utils tk-dev libffi-dev liblzma-dev
|
|
||||||
if [[ "${{ matrix.python-version }}" =~ pypy.*-(src|dev) ]]; then
|
|
||||||
export PYENV_BOOTSTRAP_VERSION=pypy2.7-7
|
|
||||||
echo "PYENV_BOOTSTRAP_VERSION=$PYENV_BOOTSTRAP_VERSION" >> $GITHUB_ENV
|
|
||||||
pyenv install $PYENV_BOOTSTRAP_VERSION
|
|
||||||
fi
|
|
||||||
- run: |
|
|
||||||
#build
|
|
||||||
pyenv install -v ${{ matrix.python-version }}
|
|
||||||
pyenv global ${{ matrix.python-version }}
|
|
||||||
# Micropython doesn't support --version
|
|
||||||
- run: |
|
|
||||||
#print version
|
|
||||||
if [[ "${{ matrix.python-version }}" == "micropython-"* ]]; then
|
|
||||||
python -c 'import sys; print(sys.version)'
|
|
||||||
else
|
|
||||||
python --version
|
|
||||||
python -m pip --version
|
|
||||||
fi
|
|
||||||
# Micropython doesn't support sys.executable, os.path, older versions even os
|
|
||||||
- env:
|
|
||||||
EXPECTED_PYTHON: ${{ matrix.python-version }}
|
|
||||||
run: |
|
|
||||||
#check
|
|
||||||
if [[ "${{ matrix.python-version }}" == "micropython-"* ]]; then
|
|
||||||
[[ $(pyenv which python) == "${{ env.PYENV_ROOT }}/versions/${{ matrix.python-version }}/bin/python" ]] || exit 1
|
|
||||||
python -c 'import sys; assert sys.implementation.name == "micropython"'
|
|
||||||
else
|
|
||||||
python -c 'if True:
|
|
||||||
import os, sys, os.path
|
|
||||||
correct_dir = os.path.join(
|
|
||||||
os.environ["PYENV_ROOT"],
|
|
||||||
"versions",
|
|
||||||
os.environ["EXPECTED_PYTHON"],
|
|
||||||
"bin")
|
|
||||||
assert os.path.dirname(sys.executable) == correct_dir'
|
|
||||||
fi
|
|
||||||
30
.github/workflows/no-response.yml
vendored
30
.github/workflows/no-response.yml
vendored
@@ -1,30 +0,0 @@
|
|||||||
name: No Response
|
|
||||||
|
|
||||||
# Both `issue_comment` and `scheduled` event types are required for this Action
|
|
||||||
# to work properly.
|
|
||||||
on:
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
schedule:
|
|
||||||
# Schedule for ten minutes after the hour, every hour
|
|
||||||
- cron: '10 * * * *'
|
|
||||||
|
|
||||||
permissions: {}
|
|
||||||
jobs:
|
|
||||||
noResponse:
|
|
||||||
permissions:
|
|
||||||
issues: write # to update issues (lee-dohm/no-response)
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: lee-dohm/no-response@v0.5.0
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
daysUntilClose: 30
|
|
||||||
responseRequiredLabel: need-feedback
|
|
||||||
closeComment: >
|
|
||||||
This issue has been automatically closed because there has been no response
|
|
||||||
to our request for more information from the original author. With only the
|
|
||||||
information that is currently in the issue, we don't have enough information
|
|
||||||
to take action. Please reach out if you have or find the answers we need so
|
|
||||||
that we can investigate further.
|
|
||||||
49
.github/workflows/pyenv_tests.yml
vendored
49
.github/workflows/pyenv_tests.yml
vendored
@@ -1,49 +0,0 @@
|
|||||||
name: pyenv_tests
|
|
||||||
on: [pull_request, push]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read # to fetch code (actions/checkout)
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
pyenv_tests:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os:
|
|
||||||
- ubuntu-22.04
|
|
||||||
- ubuntu-20.04
|
|
||||||
- macos-12
|
|
||||||
- macos-11
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# Normally, we would use the superbly maintained...
|
|
||||||
# - 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
|
|
||||||
- run: |
|
|
||||||
if test "$RUNNER_OS" == "macOS"; then
|
|
||||||
brew install coreutils fish
|
|
||||||
elif [[ $(lsb_release -sr | awk -F. '{print $1}') -ge 20 ]]; then
|
|
||||||
# Ubuntu 18 has fish 2 which lacks many features that facilitate testing
|
|
||||||
sudo apt install fish -yq
|
|
||||||
fi
|
|
||||||
- run: pwd
|
|
||||||
- env:
|
|
||||||
PYENV_ROOT: /home/runner/work/pyenv/pyenv
|
|
||||||
run: |
|
|
||||||
echo $PYENV_ROOT
|
|
||||||
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
|
|
||||||
- run: |
|
|
||||||
make test
|
|
||||||
- env:
|
|
||||||
PYENV_NATIVE_EXT: 1
|
|
||||||
run: |
|
|
||||||
(cd src; ./configure; make)
|
|
||||||
bats/bin/bats test/{pyenv,hooks,versions}.bats
|
|
||||||
16
.github/workflows/release.yml
vendored
Normal file
16
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
name: Release
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
homebrew:
|
||||||
|
name: Bump Homebrew formula
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: mislav/bump-homebrew-formula-action@v3.2
|
||||||
|
if: "!contains(github.ref, '-')" # skip prereleases
|
||||||
|
with:
|
||||||
|
formula-name: rbenv
|
||||||
|
env:
|
||||||
|
COMMITTER_TOKEN: ${{ secrets.COMMITTER_TOKEN }}
|
||||||
45
.github/workflows/ubuntu_build.yml
vendored
45
.github/workflows/ubuntu_build.yml
vendored
@@ -1,45 +0,0 @@
|
|||||||
name: ubuntu_build
|
|
||||||
on: [pull_request, push]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read # to fetch code (actions/checkout)
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ubuntu_build:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
python-version:
|
|
||||||
- "3.8"
|
|
||||||
- "3.9"
|
|
||||||
- "3.10"
|
|
||||||
- "3.11"
|
|
||||||
- "3.12"
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# Normally, we would use the superbly maintained...
|
|
||||||
# - 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 update -q; sudo apt install -yq make build-essential libssl-dev zlib1g-dev \
|
|
||||||
libbz2-dev libreadline-dev libsqlite3-dev curl \
|
|
||||||
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
|
|
||||||
# https://github.com/pyenv/pyenv#installation
|
|
||||||
- run: pwd
|
|
||||||
- env:
|
|
||||||
PYENV_ROOT: /home/runner/work/pyenv/pyenv
|
|
||||||
run: |
|
|
||||||
echo $PYENV_ROOT
|
|
||||||
echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH
|
|
||||||
bin/pyenv --debug install ${{ matrix.python-version }}
|
|
||||||
bin/pyenv global ${{ matrix.python-version }}
|
|
||||||
bin/pyenv rehash
|
|
||||||
- run: python --version
|
|
||||||
- run: python -m pip --version
|
|
||||||
- shell: python # Prove that actual Python == expected Python
|
|
||||||
env:
|
|
||||||
EXPECTED_PYTHON: ${{ matrix.python-version }}
|
|
||||||
run: import os, sys ; assert sys.version.startswith(os.getenv("EXPECTED_PYTHON"))
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
/plugins
|
||||||
/shims
|
/shims
|
||||||
/version
|
/version
|
||||||
/versions
|
/versions
|
||||||
@@ -6,7 +7,4 @@
|
|||||||
/libexec/*.dylib
|
/libexec/*.dylib
|
||||||
/src/Makefile
|
/src/Makefile
|
||||||
/src/*.o
|
/src/*.o
|
||||||
/bats/
|
/gems
|
||||||
/default-packages
|
|
||||||
.idea
|
|
||||||
*.un~
|
|
||||||
|
|||||||
1311
CHANGELOG.md
1311
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -67,9 +67,9 @@ members of the project's leadership.
|
|||||||
|
|
||||||
## Project Maintainers
|
## Project Maintainers
|
||||||
|
|
||||||
* Yamashita, Yuu <<peek824545201@gmail.com>>
|
* Sam Stephenson <<sstephenson@gmail.com>>
|
||||||
* Daniel Hahler <<git@thequod.de>>
|
* Mislav Marohnić <<mislav.marohnic@gmail.com>>
|
||||||
* Josh Friend <<josh@fueledbycaffeine.com>>
|
* Erik Michaels-Ober <<sferik@gmail.com>>
|
||||||
|
|
||||||
## Attribution
|
## Attribution
|
||||||
|
|
||||||
401
COMMANDS.md
401
COMMANDS.md
@@ -1,401 +0,0 @@
|
|||||||
# Command Reference
|
|
||||||
|
|
||||||
Like `git`, the `pyenv` command delegates to subcommands based on its
|
|
||||||
first argument.
|
|
||||||
|
|
||||||
The most common subcommands are:
|
|
||||||
|
|
||||||
* [`pyenv help`](#pyenv-help)
|
|
||||||
* [`pyenv commands`](#pyenv-commands)
|
|
||||||
* [`pyenv local`](#pyenv-local)
|
|
||||||
* [`pyenv global`](#pyenv-global)
|
|
||||||
* [`pyenv shell`](#pyenv-shell)
|
|
||||||
* [`pyenv install`](#pyenv-install)
|
|
||||||
* [`pyenv uninstall`](#pyenv-uninstall)
|
|
||||||
* [`pyenv rehash`](#pyenv-rehash)
|
|
||||||
* [`pyenv version`](#pyenv-version)
|
|
||||||
* [`pyenv versions`](#pyenv-versions)
|
|
||||||
* [`pyenv which`](#pyenv-which)
|
|
||||||
* [`pyenv whence`](#pyenv-whence)
|
|
||||||
* [`pyenv exec`](#pyenv-exec)
|
|
||||||
* [`pyenv root`](#pyenv-root)
|
|
||||||
* [`pyenv prefix`](#pyenv-prefix)
|
|
||||||
* [`pyenv latest`](#pyenv-latest)
|
|
||||||
* [`pyenv hooks`](#pyenv-hooks)
|
|
||||||
* [`pyenv shims`](#pyenv-shims)
|
|
||||||
* [`pyenv init`](#pyenv-init)
|
|
||||||
* [`pyenv completions`](#pyenv-completions)
|
|
||||||
|
|
||||||
## `pyenv help`
|
|
||||||
|
|
||||||
List all available pyenv commands along with a brief description of what they do. Run `pyenv help <command>` for information on a specific command. For full documentation, see: https://github.com/pyenv/pyenv#readme
|
|
||||||
|
|
||||||
|
|
||||||
## `pyenv commands`
|
|
||||||
|
|
||||||
Lists all available pyenv commands.
|
|
||||||
|
|
||||||
|
|
||||||
## `pyenv local`
|
|
||||||
|
|
||||||
Sets a local application-specific Python version by writing the version
|
|
||||||
name to a `.python-version` file in the current directory. This version
|
|
||||||
overrides the global version, and can be overridden itself by setting
|
|
||||||
the `PYENV_VERSION` environment variable or with the `pyenv shell`
|
|
||||||
command.
|
|
||||||
|
|
||||||
$ pyenv local 2.7.6
|
|
||||||
|
|
||||||
When run without a version number, `pyenv local` reports the currently
|
|
||||||
configured local version. You can also unset the local version:
|
|
||||||
|
|
||||||
$ pyenv local --unset
|
|
||||||
|
|
||||||
Previous versions of pyenv stored local version specifications in a
|
|
||||||
file named `.pyenv-version`. For backwards compatibility, pyenv will
|
|
||||||
read a local version specified in an `.pyenv-version` file, but a
|
|
||||||
`.python-version` file in the same directory will take precedence.
|
|
||||||
|
|
||||||
|
|
||||||
### `pyenv local` (advanced)
|
|
||||||
|
|
||||||
You can specify multiple versions as local Python at once.
|
|
||||||
|
|
||||||
Let's say if you have two versions of 2.7.6 and 3.3.3. If you prefer 2.7.6 over 3.3.3,
|
|
||||||
|
|
||||||
$ pyenv local 2.7.6 3.3.3
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2.7.6 (set by /Users/yyuu/path/to/project/.python-version)
|
|
||||||
* 3.3.3 (set by /Users/yyuu/path/to/project/.python-version)
|
|
||||||
$ python --version
|
|
||||||
Python 2.7.6
|
|
||||||
$ python2.7 --version
|
|
||||||
Python 2.7.6
|
|
||||||
$ python3.3 --version
|
|
||||||
Python 3.3.3
|
|
||||||
|
|
||||||
or, if you prefer 3.3.3 over 2.7.6,
|
|
||||||
|
|
||||||
$ pyenv local 3.3.3 2.7.6
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2.7.6 (set by /Users/yyuu/path/to/project/.python-version)
|
|
||||||
* 3.3.3 (set by /Users/yyuu/path/to/project/.python-version)
|
|
||||||
venv27
|
|
||||||
$ python --version
|
|
||||||
Python 3.3.3
|
|
||||||
$ python2.7 --version
|
|
||||||
Python 2.7.6
|
|
||||||
$ python3.3 --version
|
|
||||||
Python 3.3.3
|
|
||||||
|
|
||||||
|
|
||||||
## `pyenv global`
|
|
||||||
|
|
||||||
Sets the global version of Python to be used in all shells by writing
|
|
||||||
the version name to the `~/.pyenv/version` file. This version can be
|
|
||||||
overridden by an application-specific `.python-version` file, or by
|
|
||||||
setting the `PYENV_VERSION` environment variable.
|
|
||||||
|
|
||||||
$ pyenv global 2.7.6
|
|
||||||
|
|
||||||
The special version name `system` tells pyenv to use the system Python
|
|
||||||
(detected by searching your `$PATH`).
|
|
||||||
|
|
||||||
When run without a version number, `pyenv global` reports the
|
|
||||||
currently configured global version.
|
|
||||||
|
|
||||||
|
|
||||||
### `pyenv global` (advanced)
|
|
||||||
|
|
||||||
You can specify multiple versions as global Python at once.
|
|
||||||
|
|
||||||
Let's say if you have two versions of 2.7.6 and 3.3.3. If you prefer 2.7.6 over 3.3.3,
|
|
||||||
|
|
||||||
$ pyenv global 2.7.6 3.3.3
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2.7.6 (set by /Users/yyuu/.pyenv/version)
|
|
||||||
* 3.3.3 (set by /Users/yyuu/.pyenv/version)
|
|
||||||
$ python --version
|
|
||||||
Python 2.7.6
|
|
||||||
$ python2.7 --version
|
|
||||||
Python 2.7.6
|
|
||||||
$ python3.3 --version
|
|
||||||
Python 3.3.3
|
|
||||||
|
|
||||||
or, if you prefer 3.3.3 over 2.7.6,
|
|
||||||
|
|
||||||
$ pyenv global 3.3.3 2.7.6
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2.7.6 (set by /Users/yyuu/.pyenv/version)
|
|
||||||
* 3.3.3 (set by /Users/yyuu/.pyenv/version)
|
|
||||||
venv27
|
|
||||||
$ python --version
|
|
||||||
Python 3.3.3
|
|
||||||
$ python2.7 --version
|
|
||||||
Python 2.7.6
|
|
||||||
$ python3.3 --version
|
|
||||||
Python 3.3.3
|
|
||||||
|
|
||||||
|
|
||||||
## `pyenv shell`
|
|
||||||
|
|
||||||
Sets a shell-specific Python version by setting the `PYENV_VERSION`
|
|
||||||
environment variable in your shell. This version overrides
|
|
||||||
application-specific versions and the global version.
|
|
||||||
|
|
||||||
$ pyenv shell pypy-2.2.1
|
|
||||||
|
|
||||||
When run without a version number, `pyenv shell` reports the current
|
|
||||||
value of `PYENV_VERSION`. You can also unset the shell version:
|
|
||||||
|
|
||||||
$ pyenv shell --unset
|
|
||||||
|
|
||||||
Note that you'll need pyenv's shell integration enabled (step 3 of
|
|
||||||
the installation instructions) in order to use this command. If you
|
|
||||||
prefer not to use shell integration, you may simply set the
|
|
||||||
`PYENV_VERSION` variable yourself:
|
|
||||||
|
|
||||||
$ export PYENV_VERSION=pypy-2.2.1
|
|
||||||
|
|
||||||
|
|
||||||
### `pyenv shell` (advanced)
|
|
||||||
|
|
||||||
You can specify multiple versions via `PYENV_VERSION` at once.
|
|
||||||
|
|
||||||
Let's say if you have two versions of 2.7.6 and 3.3.3. If you prefer 2.7.6 over 3.3.3,
|
|
||||||
|
|
||||||
$ pyenv shell 2.7.6 3.3.3
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2.7.6 (set by PYENV_VERSION environment variable)
|
|
||||||
* 3.3.3 (set by PYENV_VERSION environment variable)
|
|
||||||
$ python --version
|
|
||||||
Python 2.7.6
|
|
||||||
$ python2.7 --version
|
|
||||||
Python 2.7.6
|
|
||||||
$ python3.3 --version
|
|
||||||
Python 3.3.3
|
|
||||||
|
|
||||||
or, if you prefer 3.3.3 over 2.7.6,
|
|
||||||
|
|
||||||
$ pyenv shell 3.3.3 2.7.6
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2.7.6 (set by PYENV_VERSION environment variable)
|
|
||||||
* 3.3.3 (set by PYENV_VERSION environment variable)
|
|
||||||
venv27
|
|
||||||
$ python --version
|
|
||||||
Python 3.3.3
|
|
||||||
$ python2.7 --version
|
|
||||||
Python 2.7.6
|
|
||||||
$ python3.3 --version
|
|
||||||
Python 3.3.3
|
|
||||||
|
|
||||||
|
|
||||||
## `pyenv install`
|
|
||||||
|
|
||||||
Install a Python version (using [`python-build`](https://github.com/pyenv/pyenv/tree/master/plugins/python-build)).
|
|
||||||
|
|
||||||
Usage: pyenv install [-f] [-kvp] <version>
|
|
||||||
pyenv install [-f] [-kvp] <definition-file>
|
|
||||||
pyenv install -l|--list
|
|
||||||
|
|
||||||
-l/--list List all available versions
|
|
||||||
-f/--force Install even if the version appears to be installed already
|
|
||||||
-s/--skip-existing Skip the installation if the version appears to be installed already
|
|
||||||
|
|
||||||
python-build options:
|
|
||||||
|
|
||||||
-k/--keep Keep source tree in $PYENV_BUILD_ROOT after installation
|
|
||||||
(defaults to $PYENV_ROOT/sources)
|
|
||||||
-v/--verbose Verbose mode: print compilation status to stdout
|
|
||||||
-p/--patch Apply a patch from stdin before building
|
|
||||||
-g/--debug Build a debug version
|
|
||||||
|
|
||||||
To list the all available versions of Python, including Anaconda, Jython, pypy, and stackless, use:
|
|
||||||
|
|
||||||
$ pyenv install --list
|
|
||||||
|
|
||||||
Then install the desired versions:
|
|
||||||
|
|
||||||
$ pyenv install 2.7.6
|
|
||||||
$ pyenv install 2.6.8
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
2.6.8
|
|
||||||
* 2.7.6 (set by /home/yyuu/.pyenv/version)
|
|
||||||
|
|
||||||
You can also install the latest version of Python in a specific version line by supplying a prefix instead of a complete name:
|
|
||||||
|
|
||||||
$ pyenv install 3.10
|
|
||||||
|
|
||||||
See the [`pyenv latest` documentation](#pyenv-latest) for details on prefix resolution.
|
|
||||||
|
|
||||||
An older option is to use the `:latest` syntax. For example, to install the latest patch version for Python 3.8 you could do:
|
|
||||||
|
|
||||||
pyenv install 3.8:latest
|
|
||||||
|
|
||||||
To install the latest major release for Python 3 try:
|
|
||||||
|
|
||||||
pyenv install 3:latest
|
|
||||||
|
|
||||||
## `pyenv uninstall`
|
|
||||||
|
|
||||||
Uninstall Python versions.
|
|
||||||
|
|
||||||
Usage: pyenv uninstall [-f|--force] <version> ...
|
|
||||||
|
|
||||||
-f Attempt to remove the specified version without prompting
|
|
||||||
for confirmation. If the version does not exist, do not
|
|
||||||
display an error message.
|
|
||||||
|
|
||||||
|
|
||||||
## `pyenv rehash`
|
|
||||||
|
|
||||||
Installs shims for all Python binaries known to pyenv (i.e.,
|
|
||||||
`~/.pyenv/versions/*/bin/*`). Run this command after you install a new
|
|
||||||
version of Python, or install a package that provides binaries.
|
|
||||||
|
|
||||||
$ pyenv rehash
|
|
||||||
|
|
||||||
|
|
||||||
## `pyenv version`
|
|
||||||
|
|
||||||
Displays the currently active Python version, along with information on
|
|
||||||
how it was set.
|
|
||||||
|
|
||||||
$ pyenv version
|
|
||||||
2.7.6 (set by /home/yyuu/.pyenv/version)
|
|
||||||
|
|
||||||
|
|
||||||
## `pyenv versions`
|
|
||||||
|
|
||||||
Lists all Python versions known to pyenv, and shows an asterisk next to
|
|
||||||
the currently active version.
|
|
||||||
|
|
||||||
$ pyenv versions
|
|
||||||
2.5.6
|
|
||||||
2.6.8
|
|
||||||
* 2.7.6 (set by /home/yyuu/.pyenv/version)
|
|
||||||
3.3.3
|
|
||||||
jython-2.5.3
|
|
||||||
pypy-2.2.1
|
|
||||||
|
|
||||||
|
|
||||||
## `pyenv which`
|
|
||||||
|
|
||||||
Displays the full path to the executable that pyenv will invoke when
|
|
||||||
you run the given command.
|
|
||||||
|
|
||||||
$ pyenv which python3.3
|
|
||||||
/home/yyuu/.pyenv/versions/3.3.3/bin/python3.3
|
|
||||||
|
|
||||||
Use --nosystem argument in case when you don't need to search command in the
|
|
||||||
system environment.
|
|
||||||
|
|
||||||
## `pyenv whence`
|
|
||||||
|
|
||||||
Lists all Python versions with the given command installed.
|
|
||||||
|
|
||||||
$ pyenv whence 2to3
|
|
||||||
2.6.8
|
|
||||||
2.7.6
|
|
||||||
3.3.3
|
|
||||||
|
|
||||||
## `pyenv exec`
|
|
||||||
|
|
||||||
Usage: pyenv exec <command> [arg1 arg2...]
|
|
||||||
|
|
||||||
Runs an executable by first preparing PATH so that the selected Python
|
|
||||||
version's `bin` directory is at the front.
|
|
||||||
|
|
||||||
For example, if the currently selected Python version is 3.9.7:
|
|
||||||
|
|
||||||
pyenv exec pip install -r requirements.txt
|
|
||||||
|
|
||||||
is equivalent to:
|
|
||||||
|
|
||||||
PATH="$PYENV_ROOT/versions/3.9.7/bin:$PATH" pip install -r requirements.txt
|
|
||||||
|
|
||||||
## `pyenv root`
|
|
||||||
|
|
||||||
Displays the root directory where versions and shims are kept.
|
|
||||||
|
|
||||||
$ pyenv root
|
|
||||||
/home/user/.pyenv
|
|
||||||
|
|
||||||
## `pyenv prefix`
|
|
||||||
|
|
||||||
Displays the directories where the given Python versions are installed,
|
|
||||||
separated by colons. If no version is given, `pyenv prefix` displays the
|
|
||||||
locations of the currently selected versions.
|
|
||||||
|
|
||||||
$ pyenv prefix 3.9.7
|
|
||||||
/home/user/.pyenv/versions/3.9.7
|
|
||||||
|
|
||||||
## `pyenv latest`
|
|
||||||
|
|
||||||
Displays the latest installed or known version with the given prefix
|
|
||||||
|
|
||||||
Usage: pyenv latest [-k|--known] [-q|--quiet] <prefix>
|
|
||||||
|
|
||||||
-k/--known Select from all known versions instead of installed
|
|
||||||
-q/--quiet Do not print an error message on resolution failure
|
|
||||||
|
|
||||||
Only full prefixes are searched: in the actual name, the given prefix must be followed by a dot or a dash.
|
|
||||||
|
|
||||||
Prereleases and versions with specific suffixes (e.g. `-src`) are ignored.
|
|
||||||
|
|
||||||
## `pyenv hooks`
|
|
||||||
|
|
||||||
Lists installed hook scripts for a given pyenv command.
|
|
||||||
|
|
||||||
Usage: pyenv hooks <command>
|
|
||||||
|
|
||||||
## `pyenv shims`
|
|
||||||
|
|
||||||
List existing pyenv shims.
|
|
||||||
|
|
||||||
Usage: pyenv shims [--short]
|
|
||||||
|
|
||||||
$ pyenv shims
|
|
||||||
/home/user/.pyenv/shims/2to3
|
|
||||||
/home/user/.pyenv/shims/2to3-3.9
|
|
||||||
/home/user/.pyenv/shims/idle
|
|
||||||
/home/user/.pyenv/shims/idle3
|
|
||||||
/home/user/.pyenv/shims/idle3.9
|
|
||||||
/home/user/.pyenv/shims/pip
|
|
||||||
/home/user/.pyenv/shims/pip3
|
|
||||||
/home/user/.pyenv/shims/pip3.9
|
|
||||||
/home/user/.pyenv/shims/pydoc
|
|
||||||
/home/user/.pyenv/shims/pydoc3
|
|
||||||
/home/user/.pyenv/shims/pydoc3.9
|
|
||||||
/home/user/.pyenv/shims/python
|
|
||||||
/home/user/.pyenv/shims/python3
|
|
||||||
/home/user/.pyenv/shims/python3.9
|
|
||||||
/home/user/.pyenv/shims/python3.9-config
|
|
||||||
/home/user/.pyenv/shims/python3.9-gdb.py
|
|
||||||
/home/user/.pyenv/shims/python3-config
|
|
||||||
/home/user/.pyenv/shims/python-config
|
|
||||||
|
|
||||||
## `pyenv init`
|
|
||||||
|
|
||||||
Configure the shell environment for pyenv
|
|
||||||
|
|
||||||
Usage: eval "$(pyenv init [-|--path] [--no-push-path] [--no-rehash] [<shell>])"
|
|
||||||
|
|
||||||
- Initialize shims directory, print PYENV_SHELL variable, completions path
|
|
||||||
and shell function
|
|
||||||
--path Print shims path
|
|
||||||
--no-push-path Do not push shim to the start of PATH if they're already there
|
|
||||||
--no-rehash Add no rehash command to output
|
|
||||||
|
|
||||||
## `pyenv completions`
|
|
||||||
|
|
||||||
Lists available completions for a given pyenv command.
|
|
||||||
|
|
||||||
Usage: pyenv completions <command> [arg1 arg2...]
|
|
||||||
109
CONTRIBUTING.md
109
CONTRIBUTING.md
@@ -1,109 +0,0 @@
|
|||||||
General guidance
|
|
||||||
================
|
|
||||||
|
|
||||||
* The usual principles of respecting existing conventions and making sure that your changes
|
|
||||||
are in line with the overall product design apply when contributing code to Pyenv.
|
|
||||||
|
|
||||||
* We are limited to Bash 3.2 features
|
|
||||||
|
|
||||||
That's because that's the version shipped with MacOS.
|
|
||||||
(They didn't upgrade past it and switched to Zsh because later versions
|
|
||||||
are covered by GPLv3 which has additional restrictions unacceptable for Apple.)
|
|
||||||
|
|
||||||
You can still add performance optimizations etc that take advantage of newer Bash features
|
|
||||||
as long as there is a fallback execution route for Bash 3.
|
|
||||||
|
|
||||||
* Be extra careful when submitting logic specific for the Apple Silicon platform
|
|
||||||
|
|
||||||
As of this writing, Github Actions do not support it and only one team member has the necessary hardware.
|
|
||||||
So we may be unable to test your changes and may have to take your word for it.
|
|
||||||
|
|
||||||
|
|
||||||
Formatting PRs
|
|
||||||
==============
|
|
||||||
|
|
||||||
We strive to keep commit history one-concern-per-commit to keep it meaningful and easy to follow.
|
|
||||||
If a pull request (PR) addresses a single concern (the typical case), we usually squash commits
|
|
||||||
from it together when merging so its commit history doesn't matter.
|
|
||||||
If however a PR addresses multiple separate concerns, each of them should be presented as a separate commit.
|
|
||||||
Adding multiple new Python releases of the same flavor is okay with either a single or multiple commits.
|
|
||||||
|
|
||||||
|
|
||||||
Authoring installation scripts
|
|
||||||
==============================
|
|
||||||
|
|
||||||
Adding new Python release support
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
The easiest way to add support for a new Python release is to copy the script from the previous one
|
|
||||||
and adjust it as necessary. In many cases, just changing version numbers, URLs and hashes is enough.
|
|
||||||
Do pay attention to other "magic numbers" that may be present in a script --
|
|
||||||
e.g. the set of architectures and OS versions supported by a release -- since those change from time to time, too.
|
|
||||||
|
|
||||||
Make sure to also copy any patches for the previous release that still apply to the new one.
|
|
||||||
Typically, a patch no longer applies if it addresses a problem that's already fixed in the new release.
|
|
||||||
|
|
||||||
For prereleases, we only create an entry for the latest prerelease in a specific version line.
|
|
||||||
When submitting a newer prerelease, replace the older one.
|
|
||||||
|
|
||||||
|
|
||||||
Adding version-specific fixes/patches
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
We accept fixes to issues in specific Python releases that prevent users from using them with Pyenv.
|
|
||||||
|
|
||||||
In the default configuration for a Python release, we strive to provide as close to vanilla experience as practical,
|
|
||||||
to maintain [the principle of the least surprise](https://en.wikipedia.org/wiki/Principle_of_least_astonishment).
|
|
||||||
As such, any such fixes:
|
|
||||||
|
|
||||||
* Must not break or degrade (e.g. disable features) the build in any of the environments that the release officially supports
|
|
||||||
* Must not introduce incompatibilities with the vanilla release (including binary incompatibilities)
|
|
||||||
* Should not patch things unnecessarily, to minimize the risk of the aforementioned undesirable side effects.
|
|
||||||
* E.g. if the fix is for a specific environment, its logic ought to only fire in this specific environment and not touch execution paths for other environments.
|
|
||||||
* As such, it's advisable to briefly explain in the PR what each added patch does and why it is necessary to fix the declared problem
|
|
||||||
|
|
||||||
Generally, version-specific fixes belong in the scripts for the affected releases and/or patches for them -- this guarantees that their effect is limited to only those releases.
|
|
||||||
|
|
||||||
<h3>Backporting upstream patches</h3>
|
|
||||||
|
|
||||||
Usually, this is the easiest way to backport a fix for a problem that is fixed in a newer release.
|
|
||||||
|
|
||||||
* Clone Python, check out the tag for the appropriate release and create a branch
|
|
||||||
* Apply existing patches if there are any (with either `patch` or `git am`) and commit
|
|
||||||
* Cherry-pick the upstream commit that fixes the problem in a newer release
|
|
||||||
* Commit and `git format-patch`
|
|
||||||
* Commit the generated patch file into Pyenv, test your changes and submit a PR
|
|
||||||
|
|
||||||
|
|
||||||
Deprecation policy
|
|
||||||
------------------
|
|
||||||
|
|
||||||
We do not provide official support for EOL releases and environments or otherwise provide any kind of extended support for old Python releases.
|
|
||||||
|
|
||||||
We do however accept fixes from interested parties that would allow running older, including EOL, releases in environments that they do not officially support.
|
|
||||||
In addition to the above requirements for release-specific fixes,
|
|
||||||
|
|
||||||
* Such a fix must not add maintenance burden (e.g. add new logic to `python-build` that has to be kept there indefinitely)
|
|
||||||
* Unless the added logic is useful for both EOL and non-EOL releases. In this case, it will be considered as being primarily an improvement for non-EOL releases.
|
|
||||||
* Support is provided on a "best effort" basis: we do not actively maintain these fixes but won't actively break them, either, and will accept any corrections.
|
|
||||||
Since old releases never change, it's pretty safe to assume that the fixes will continue to work until a later version
|
|
||||||
of an environment introduces further incompatible changes.
|
|
||||||
|
|
||||||
|
|
||||||
Advanced changes / adding new Python flavor support
|
|
||||||
---------------------------------------------------
|
|
||||||
|
|
||||||
An installation script is sourced from `python-build`. All installation scripts are based on the same logic:
|
|
||||||
|
|
||||||
1. Select the source to download and other variable parameters as needed.
|
|
||||||
|
|
||||||
This includes showing an error if the user's environment (OS, architecture) is not supported by the release.
|
|
||||||
Binary releases that only officially support specific distro(s) typically show a warning in other distros instead.
|
|
||||||
|
|
||||||
2. Run one of the `install_*` shell functions
|
|
||||||
|
|
||||||
`install_*` shell functions defined in `python-build` install Python from different kinds of sources -- compressed package (binary or source), upstream installation script, VCS checkout. Pick one that's the most appropriate for your packaging.
|
|
||||||
|
|
||||||
Each of them accepts a couple of function-specific arguments which are followed by arguments that constitute the build sequence. Each `<argument>` in the build sequence corresponds to the `install_*_<argument>` function in `python-build`. Check what's available and add any functions with logic specific to your flavor if needed.
|
|
||||||
|
|
||||||
We strive to keep out of `python-build` parts of build logic that are release-specific and/or tend to change abruptly between releases -- e.g. sets of supported architectures and other software's versions. This results in logic duplication between installation scripts -- but since old releases never change once released, this doesn't really add to the maintenance burden. As a rule of thumb, `python-build` can host parts of logic that are expected to stay the same for an indefinite amount of time -- for an entire Python flavor or release line.
|
|
||||||
35
Dockerfile
35
Dockerfile
@@ -1,35 +0,0 @@
|
|||||||
FROM ubuntu:18.04
|
|
||||||
|
|
||||||
LABEL maintainer="Chris L. Barnes <chrislloydbarnes@gmail.com>"
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
RUN apt-get update -y \
|
|
||||||
&& apt-get install -y \
|
|
||||||
make \
|
|
||||||
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 \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
ENV PYENV_ROOT "/pyenv"
|
|
||||||
ENV PATH "$PYENV_ROOT/bin:$PATH"
|
|
||||||
|
|
||||||
COPY . /pyenv
|
|
||||||
|
|
||||||
RUN eval "$(pyenv init -)"
|
|
||||||
|
|
||||||
1
LICENSE
1
LICENSE
@@ -1,4 +1,3 @@
|
|||||||
Copyright (c) 2013 Yamashita, Yuu
|
|
||||||
Copyright (c) 2013 Sam Stephenson
|
Copyright (c) 2013 Sam Stephenson
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
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/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 `libexec/pyenv---version`
|
|
||||||
* 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
|
|
||||||
31
Makefile
31
Makefile
@@ -1,29 +1,4 @@
|
|||||||
.PHONY: test test-build test-unit test-plugin
|
release_version := $(shell GIT_CEILING_DIRECTORIES=$(PWD) bin/rbenv --version | cut -d' ' -f2)
|
||||||
|
|
||||||
# Do not pass in user flags to build tests.
|
share/man/man1/rbenv.1: share/man/man1/rbenv.1.adoc
|
||||||
unexport PYTHON_CFLAGS
|
asciidoctor -b manpage -a version=$(release_version:v%=%) $<
|
||||||
unexport PYTHON_CONFIGURE_OPTS
|
|
||||||
|
|
||||||
test: test-unit test-plugin
|
|
||||||
|
|
||||||
test-unit: bats
|
|
||||||
PATH="./bats/bin:$$PATH" test/run
|
|
||||||
|
|
||||||
test-plugin: bats
|
|
||||||
cd plugins/python-build && $(PWD)/bats/bin/bats $${CI:+--tap} test
|
|
||||||
|
|
||||||
PYTHON_BUILD_ROOT := $(CURDIR)/plugins/python-build
|
|
||||||
PYTHON_BUILD_OPTS ?= --verbose
|
|
||||||
PYTHON_BUILD_VERSION ?= 3.8-dev
|
|
||||||
PYTHON_BUILD_TEST_PREFIX ?= $(PYTHON_BUILD_ROOT)/test/build/tmp/dist
|
|
||||||
|
|
||||||
test-build:
|
|
||||||
$(RM) -r $(PYTHON_BUILD_TEST_PREFIX)
|
|
||||||
$(PYTHON_BUILD_ROOT)/bin/python-build $(PYTHON_BUILD_OPTS) $(PYTHON_BUILD_VERSION) $(PYTHON_BUILD_TEST_PREFIX)
|
|
||||||
[ -e $(PYTHON_BUILD_TEST_PREFIX)/bin/python ]
|
|
||||||
$(PYTHON_BUILD_TEST_PREFIX)/bin/python -V
|
|
||||||
[ -e $(PYTHON_BUILD_TEST_PREFIX)/bin/pip ]
|
|
||||||
$(PYTHON_BUILD_TEST_PREFIX)/bin/pip -V
|
|
||||||
|
|
||||||
bats:
|
|
||||||
git clone --depth 1 --branch v1.2.0 https://github.com/bats-core/bats-core.git bats
|
|
||||||
|
|||||||
923
README.md
923
README.md
@@ -1,715 +1,350 @@
|
|||||||
# Simple Python Version Management: pyenv
|
# Seamlessly manage your app’s Ruby environment with rbenv.
|
||||||
|
|
||||||
[](https://gitter.im/yyuu/pyenv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
||||||
|
|
||||||
pyenv lets you easily switch between multiple versions of Python. It's
|
|
||||||
simple, unobtrusive, and follows the UNIX tradition of single-purpose
|
|
||||||
tools that do one thing well.
|
|
||||||
|
|
||||||
This project was forked from [rbenv](https://github.com/rbenv/rbenv) and
|
|
||||||
[ruby-build](https://github.com/rbenv/ruby-build), and modified for Python.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### What pyenv _does..._
|
|
||||||
|
|
||||||
* Lets you **change the global Python version** on a per-user basis.
|
|
||||||
* Provides support for **per-project Python versions**.
|
|
||||||
* Allows you to **override the Python version** with an environment
|
|
||||||
variable.
|
|
||||||
* Searches for commands from **multiple versions of Python at a time**.
|
|
||||||
This may be helpful to test across Python versions with [tox](https://pypi.python.org/pypi/tox).
|
|
||||||
|
|
||||||
|
|
||||||
### In contrast with pythonbrew and pythonz, pyenv _does not..._
|
|
||||||
|
|
||||||
* **Depend on Python itself.** pyenv was made from pure shell scripts.
|
|
||||||
There is no bootstrap problem of Python.
|
|
||||||
* **Need to be loaded into your shell.** Instead, pyenv's shim
|
|
||||||
approach works by adding a directory to your `PATH`.
|
|
||||||
* **Manage virtualenv.** Of course, you can create [virtualenv](https://pypi.python.org/pypi/virtualenv)
|
|
||||||
yourself, or [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv)
|
|
||||||
to automate the process.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
* **[How It Works](#how-it-works)**
|
|
||||||
* [Understanding PATH](#understanding-path)
|
|
||||||
* [Understanding Shims](#understanding-shims)
|
|
||||||
* [Understanding Python version selection](#understanding-python-version-selection)
|
|
||||||
* [Locating Pyenv-provided Python Installations](#locating-pyenv-provided-python-installations)
|
|
||||||
* **[Installation](#installation)**
|
|
||||||
* [Getting Pyenv](#getting-pyenv)
|
|
||||||
* [UNIX/MacOS](#unixmacos)
|
|
||||||
* [Homebrew in macOS](#homebrew-in-macos)
|
|
||||||
* [Automatic installer](#automatic-installer)
|
|
||||||
* [Basic GitHub Checkout](#basic-github-checkout)
|
|
||||||
* [Windows](#windows)
|
|
||||||
* [Set up your shell environment for Pyenv](#set-up-your-shell-environment-for-pyenv)
|
|
||||||
* [Restart your shell](#restart-your-shell)
|
|
||||||
* [Install Python build dependencies](#install-python-build-dependencies)
|
|
||||||
* **[Usage](#usage)**
|
|
||||||
* [Install additional Python versions](#install-additional-python-versions)
|
|
||||||
* [Prefix auto-resolution to the latest version](#prefix-auto-resolution-to-the-latest-version)
|
|
||||||
* [Python versions with extended support](#python-versions-with-extended-support)
|
|
||||||
* [Switch between Python versions](#switch-between-python-versions)
|
|
||||||
* [Uninstall Python versions](#uninstall-python-versions)
|
|
||||||
* [Other operations](#other-operations)
|
|
||||||
* [Upgrading](#upgrading)
|
|
||||||
* [Upgrading with Homebrew](#upgrading-with-homebrew)
|
|
||||||
* [Upgrading with Installer or Git checkout](#upgrading-with-installer-or-git-checkout)
|
|
||||||
* [Uninstalling pyenv](#uninstalling-pyenv)
|
|
||||||
* [Pyenv plugins](#pyenv-plugins)
|
|
||||||
* [Advanced Configuration](#advanced-configuration)
|
|
||||||
* [Using Pyenv without shims](#using-pyenv-without-shims)
|
|
||||||
* [Environment variables](#environment-variables)
|
|
||||||
* **[Development](#development)**
|
|
||||||
* [Contributing](#contributing)
|
|
||||||
* [Version History](#version-history)
|
|
||||||
* [License](#license)
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
|
rbenv is a version manager tool for the Ruby programming language on Unix-like systems. It is useful for switching between multiple Ruby versions on the same machine and for ensuring that each project you are working on always runs on the correct Ruby version.
|
||||||
|
|
||||||
## How It Works
|
## How It Works
|
||||||
|
|
||||||
At a high level, pyenv intercepts Python commands using shim
|
After rbenv injects itself into your PATH at installation time, any invocation of `ruby`, `gem`, `bundler`, or other Ruby-related executable will first activate rbenv. Then, rbenv scans the current project directory for a file named `.ruby-version`. If found, that file determines the version of Ruby that should be used within that directory. Finally, rbenv looks up that Ruby version among those installed under `~/.rbenv/versions/`.
|
||||||
executables injected into your `PATH`, determines which Python version
|
|
||||||
has been specified by your application, and passes your commands along
|
|
||||||
to the correct Python installation.
|
|
||||||
|
|
||||||
|
You can choose the Ruby version for your project with, for example:
|
||||||
|
```sh
|
||||||
|
cd myproject
|
||||||
|
# choose Ruby version 3.1.2:
|
||||||
|
rbenv local 3.1.2
|
||||||
|
```
|
||||||
|
|
||||||
### Understanding PATH
|
Doing so will create or update the `.ruby-version` file in the current directory with the version that you've chosen. A different project of yours that is another directory might be using a different version of Ruby altogether—rbenv will seamlessly transition from one Ruby version to another when you switch projects.
|
||||||
|
|
||||||
When you run a command like `python` or `pip`, your shell (bash / zshrc / ...)
|
Finally, almost every aspect of rbenv's mechanism is [customizable via plugins][plugins] written in bash.
|
||||||
searches through a list of directories to find an executable file with
|
|
||||||
that name. This list of directories lives in an environment variable
|
|
||||||
called `PATH`, with each directory in the list separated by a colon:
|
|
||||||
|
|
||||||
/usr/local/bin:/usr/bin:/bin
|
|
||||||
|
|
||||||
Directories in `PATH` are searched from left to right, so a matching
|
|
||||||
executable in a directory at the beginning of the list takes
|
|
||||||
precedence over another one at the end. In this example, the
|
|
||||||
`/usr/local/bin` directory will be searched first, then `/usr/bin`,
|
|
||||||
then `/bin`.
|
|
||||||
|
|
||||||
|
|
||||||
### Understanding Shims
|
|
||||||
|
|
||||||
pyenv works by inserting a directory of _shims_ at the front of your
|
|
||||||
`PATH`:
|
|
||||||
|
|
||||||
$(pyenv root)/shims:/usr/local/bin:/usr/bin:/bin
|
|
||||||
|
|
||||||
Through a process called _rehashing_, pyenv maintains shims in that
|
|
||||||
directory to match every Python command across every installed version
|
|
||||||
of Python—`python`, `pip`, and so on.
|
|
||||||
|
|
||||||
Shims are lightweight executables that simply pass your command along
|
|
||||||
to pyenv. So with pyenv installed, when you run, say, `pip`, your
|
|
||||||
operating system will do the following:
|
|
||||||
|
|
||||||
* Search your `PATH` for an executable file named `pip`
|
|
||||||
* Find the pyenv shim named `pip` at the beginning of your `PATH`
|
|
||||||
* Run the shim named `pip`, which in turn passes the command along to
|
|
||||||
pyenv
|
|
||||||
|
|
||||||
|
|
||||||
### Understanding Python version selection
|
|
||||||
|
|
||||||
When you execute a shim, pyenv determines which Python version to use by
|
|
||||||
reading it from the following sources, in this order:
|
|
||||||
|
|
||||||
1. The `PYENV_VERSION` environment variable (if specified). You can use
|
|
||||||
the [`pyenv shell`](https://github.com/pyenv/pyenv/blob/master/COMMANDS.md#pyenv-shell) command to set this environment
|
|
||||||
variable in your current shell session.
|
|
||||||
|
|
||||||
2. The application-specific `.python-version` file in the current
|
|
||||||
directory (if present). You can modify the current directory's
|
|
||||||
`.python-version` file with the [`pyenv local`](https://github.com/pyenv/pyenv/blob/master/COMMANDS.md#pyenv-local)
|
|
||||||
command.
|
|
||||||
|
|
||||||
3. The first `.python-version` file found (if any) by searching each parent
|
|
||||||
directory, until reaching the root of your filesystem.
|
|
||||||
|
|
||||||
4. The global `$(pyenv root)/version` file. You can modify this file using
|
|
||||||
the [`pyenv global`](https://github.com/pyenv/pyenv/blob/master/COMMANDS.md#pyenv-global) command.
|
|
||||||
If the global version file is not present, pyenv assumes you want to use the "system"
|
|
||||||
Python (see below).
|
|
||||||
|
|
||||||
A special version name "`system`" means to use whatever Python is found on `PATH`
|
|
||||||
after the shims `PATH` entry (in other words, whatever would be run if Pyenv
|
|
||||||
shims weren't on `PATH`). Note that Pyenv considers those installations outside
|
|
||||||
its control and does not attempt to inspect or distinguish them in any way.
|
|
||||||
So e.g. if you are on MacOS and have OS-bundled Python 3.8.9 and Homebrew-installed
|
|
||||||
Python 3.9.12 and 3.10.2 -- for Pyenv, this is still a single "`system`" version,
|
|
||||||
and whichever of those is first on `PATH` under the executable name you
|
|
||||||
specified will be run.
|
|
||||||
|
|
||||||
**NOTE:** You can activate multiple versions at the same time, including multiple
|
|
||||||
versions of Python2 or Python3 simultaneously. This allows for parallel usage of
|
|
||||||
Python2 and Python3, and is required with tools like `tox`. For example, to instruct
|
|
||||||
Pyenv to first use your system Python and Python3 (which are e.g. 2.7.9 and 3.4.2)
|
|
||||||
but also have Python 3.3.6, 3.2.1, and 2.5.2 available, you first `pyenv install`
|
|
||||||
the missing versions, then set `pyenv global system 3.3.6 3.2.1 2.5.2`.
|
|
||||||
Then you'll be able to invoke any of those versions with an appropriate `pythonX` or
|
|
||||||
`pythonX.Y` name.
|
|
||||||
You can also specify multiple versions in a `.python-version` file by hand,
|
|
||||||
separated by newlines. Lines starting with a `#` are ignored.
|
|
||||||
|
|
||||||
[`pyenv which <command>`](COMMANDS.md#pyenv-which) displays which real executable would be
|
|
||||||
run when you invoke `<command>` via a shim.
|
|
||||||
E.g. if you have 3.3.6, 3.2.1 and 2.5.2 installed of which 3.3.6 and 2.5.2 are selected
|
|
||||||
and your system Python is 3.2.5,
|
|
||||||
`pyenv which python2.5` should display `$(pyenv root)/versions/2.5.2/bin/python2.5`,
|
|
||||||
`pyenv which python3` -- `$(pyenv root)/versions/3.3.6/bin/python3` and
|
|
||||||
`pyenv which python3.2` -- path to your system Python due to the fall-through (see below).
|
|
||||||
|
|
||||||
Shims also fall through to anything further on `PATH` if the corresponding executable is
|
|
||||||
not present in any of the selected Python installations.
|
|
||||||
This allows you to use any programs installed elsewhere on the system as long as
|
|
||||||
they are not shadowed by a selected Python installation.
|
|
||||||
|
|
||||||
|
|
||||||
### Locating Pyenv-provided Python installations
|
|
||||||
|
|
||||||
Once pyenv has determined which version of Python your application has
|
|
||||||
specified, it passes the command along to the corresponding Python
|
|
||||||
installation.
|
|
||||||
|
|
||||||
Each Python version is installed into its own directory under
|
|
||||||
`$(pyenv root)/versions`.
|
|
||||||
|
|
||||||
For example, you might have these versions installed:
|
|
||||||
|
|
||||||
* `$(pyenv root)/versions/2.7.8/`
|
|
||||||
* `$(pyenv root)/versions/3.4.2/`
|
|
||||||
* `$(pyenv root)/versions/pypy-2.4.0/`
|
|
||||||
|
|
||||||
As far as Pyenv is concerned, version names are simply directories under
|
|
||||||
`$(pyenv root)/versions`.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
|
The simplicity of rbenv has its benefits, but also some downsides. See the [comparison of version managers][alternatives] for more details and some alternatives.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### Getting Pyenv
|
On systems with Homebrew package manager, the “Using Package Managers” method is recommended. On other systems, “Basic Git Checkout” might be the easiest way of ensuring that you are always installing the latest version of rbenv.
|
||||||
#### UNIX/MacOS
|
|
||||||
##### Homebrew in macOS
|
|
||||||
|
|
||||||
1. Consider installing with [Homebrew](https://brew.sh):
|
### Using Package Managers
|
||||||
```sh
|
|
||||||
brew update
|
|
||||||
brew install pyenv
|
|
||||||
```
|
|
||||||
If you want to install (and update to) the latest development head of Pyenv
|
|
||||||
rather than the latest release, instead run:
|
|
||||||
```sh
|
|
||||||
brew install pyenv --head
|
|
||||||
```
|
|
||||||
3. Then follow the rest of the post-installation steps, starting with
|
|
||||||
[Set up your shell environment for Pyenv](#set-up-your-shell-environment-for-pyenv).
|
|
||||||
|
|
||||||
4. OPTIONAL. To fix `brew doctor`'s warning _""config" scripts exist outside your system or Homebrew directories"_
|
1. Install rbenv using one of the following approaches.
|
||||||
|
|
||||||
If you're going to build Homebrew formulae from source that link against Python
|
#### Homebrew
|
||||||
like Tkinter or NumPy
|
|
||||||
_(This is only generally the case if you are a developer of such a formula,
|
|
||||||
or if you have an EOL version of MacOS for which prebuilt bottles are no longer provided
|
|
||||||
and you are using such a formula)._
|
|
||||||
|
|
||||||
To avoid them accidentally linking against a Pyenv-provided Python,
|
On macOS or Linux, we recommend installing rbenv with [Homebrew](https://brew.sh).
|
||||||
add the following line into your interactive shell's configuration:
|
|
||||||
|
|
||||||
* Bash/Zsh:
|
```sh
|
||||||
|
brew install rbenv
|
||||||
|
```
|
||||||
|
|
||||||
~~~bash
|
#### Debian, Ubuntu, and their derivatives
|
||||||
alias brew='env PATH="${PATH//$(pyenv root)\/shims:/}" brew'
|
|
||||||
~~~
|
|
||||||
|
|
||||||
* Fish:
|
> [!CAUTION]
|
||||||
|
> The version of rbenv that is packaged and maintained in official
|
||||||
|
Debian and Ubuntu repositories is _out of date_. To install the latest
|
||||||
|
version, it is recommended to [install rbenv using git](#basic-git-checkout).
|
||||||
|
|
||||||
~~~fish
|
```sh
|
||||||
alias brew="env PATH=(string replace (pyenv root)/shims '' \"\$PATH\") brew"
|
sudo apt install rbenv
|
||||||
~~~
|
```
|
||||||
|
|
||||||
|
#### Arch Linux and its derivatives
|
||||||
|
|
||||||
##### Automatic installer
|
Archlinux has an [AUR Package](https://aur.archlinux.org/packages/rbenv/) for
|
||||||
|
rbenv and you can install it from the AUR using the instructions from this
|
||||||
|
[wiki page](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_and_upgrading_packages).
|
||||||
|
|
||||||
```bash
|
#### Fedora
|
||||||
curl https://pyenv.run | bash
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details visit our other project:
|
Fedora has an [official package](https://packages.fedoraproject.org/pkgs/rbenv/rbenv/) which you can install:
|
||||||
https://github.com/pyenv/pyenv-installer
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo dnf install rbenv
|
||||||
|
```
|
||||||
|
|
||||||
##### Basic GitHub Checkout
|
2. Set up your shell to load rbenv.
|
||||||
|
|
||||||
This will get you going with the latest version of Pyenv and make it
|
|
||||||
easy to fork and contribute any changes back upstream.
|
|
||||||
|
|
||||||
* **Check out Pyenv where you want it installed.**
|
|
||||||
A good place to choose is `$HOME/.pyenv` (but you can install it somewhere else):
|
|
||||||
```
|
|
||||||
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
|
|
||||||
```
|
|
||||||
* Optionally, try to compile a dynamic Bash extension to speed up Pyenv. Don't
|
|
||||||
worry if it fails; Pyenv will still work normally:
|
|
||||||
```
|
|
||||||
cd ~/.pyenv && src/configure && make -C src
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Windows
|
|
||||||
|
|
||||||
Pyenv does not officially support Windows and does not work in Windows outside
|
|
||||||
the Windows Subsystem for Linux.
|
|
||||||
Moreover, even there, the Pythons it installs are not native Windows versions
|
|
||||||
but rather Linux versions running in a virtual machine --
|
|
||||||
so you won't get Windows-specific functionality.
|
|
||||||
|
|
||||||
If you're in Windows, we recommend using @kirankotari's [`pyenv-win`](https://github.com/pyenv-win/pyenv-win) fork --
|
|
||||||
which does install native Windows Python versions.
|
|
||||||
|
|
||||||
|
|
||||||
### Set up your shell environment for Pyenv
|
|
||||||
|
|
||||||
**Upgrade note:** The startup logic and instructions have been updated for simplicity in 2.3.0.
|
|
||||||
The previous, more complicated configuration scheme for 2.0.0-2.2.5 still works.
|
|
||||||
|
|
||||||
* Define environment variable `PYENV_ROOT` to point to the path where
|
|
||||||
Pyenv will store its data. `$HOME/.pyenv` is the default.
|
|
||||||
If you installed Pyenv via Git checkout, we recommend
|
|
||||||
to set it to the same location as where you cloned it.
|
|
||||||
* Add the `pyenv` executable to your `PATH` if it's not already there
|
|
||||||
* run `eval "$(pyenv init -)"` to install `pyenv` into your shell as a shell function, enable shims and autocompletion
|
|
||||||
* You may run `eval "$(pyenv init --path)"` instead to just enable shims, without shell integration
|
|
||||||
|
|
||||||
The below setup should work for the vast majority of users for common use cases.
|
|
||||||
See [Advanced configuration](#advanced-configuration) for details and more configuration options.
|
|
||||||
|
|
||||||
- For **bash**:
|
|
||||||
|
|
||||||
Stock Bash startup files vary widely between distributions in which of them source
|
|
||||||
which, under what circumstances, in what order and what additional configuration they perform.
|
|
||||||
As such, the most reliable way to get Pyenv in all environments is to append Pyenv
|
|
||||||
configuration commands to both `.bashrc` (for interactive shells)
|
|
||||||
and the profile file that Bash would use (for login shells).
|
|
||||||
|
|
||||||
First, add the commands to `~/.bashrc` by running the following in your terminal:
|
|
||||||
|
|
||||||
~~~ bash
|
|
||||||
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
|
|
||||||
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
|
|
||||||
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Then, if you have `~/.profile`, `~/.bash_profile` or `~/.bash_login`, add the commands there as well.
|
|
||||||
If you have none of these, add them to `~/.profile`.
|
|
||||||
|
|
||||||
* to add to `~/.profile`:
|
|
||||||
~~~ bash
|
|
||||||
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.profile
|
|
||||||
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.profile
|
|
||||||
echo 'eval "$(pyenv init -)"' >> ~/.profile
|
|
||||||
~~~
|
|
||||||
|
|
||||||
* to add to `~/.bash_profile`:
|
|
||||||
~~~ bash
|
|
||||||
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
|
|
||||||
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
|
|
||||||
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
|
|
||||||
~~~
|
|
||||||
|
|
||||||
- For **Zsh**:
|
|
||||||
~~~ zsh
|
|
||||||
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
|
|
||||||
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
|
|
||||||
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
|
|
||||||
~~~
|
|
||||||
|
|
||||||
If you wish to get Pyenv in noninteractive login shells as well, also add the commands to `~/.zprofile` or `~/.zlogin`.
|
|
||||||
|
|
||||||
- For **Fish shell**:
|
|
||||||
|
|
||||||
If you have Fish 3.2.0 or newer, execute this interactively:
|
|
||||||
|
|
||||||
~~~ fish
|
|
||||||
set -Ux PYENV_ROOT $HOME/.pyenv
|
|
||||||
fish_add_path $PYENV_ROOT/bin
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Otherwise, execute the snippet below:
|
|
||||||
|
|
||||||
~~~ fish
|
|
||||||
set -Ux PYENV_ROOT $HOME/.pyenv
|
|
||||||
set -U fish_user_paths $PYENV_ROOT/bin $fish_user_paths
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Now, add this to `~/.config/fish/config.fish`:
|
|
||||||
|
|
||||||
~~~ fish
|
|
||||||
pyenv init - | source
|
|
||||||
~~~
|
|
||||||
|
|
||||||
**Bash warning**: There are some systems where the `BASH_ENV` variable is configured
|
|
||||||
to point to `.bashrc`. On such systems, you should almost certainly put the
|
|
||||||
`eval "$(pyenv init -)"` line into `.bash_profile`, and **not** into `.bashrc`. Otherwise, you
|
|
||||||
may observe strange behaviour, such as `pyenv` getting into an infinite loop.
|
|
||||||
See [#264](https://github.com/pyenv/pyenv/issues/264) for details.
|
|
||||||
|
|
||||||
**Proxy note**: If you use a proxy, export `http_proxy` and `https_proxy`, too.
|
|
||||||
|
|
||||||
In MacOS, you might also want to install [Fig](https://fig.io/) which
|
|
||||||
provides alternative shell completions for many command line tools with an
|
|
||||||
IDE-like popup interface in the terminal window.
|
|
||||||
(Note that their completions are independent from Pyenv's codebase
|
|
||||||
so they might be slightly out of sync for bleeding-edge interface changes.)
|
|
||||||
|
|
||||||
### Restart your shell
|
|
||||||
|
|
||||||
for the `PATH` changes to take effect.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
exec "$SHELL"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Install Python build dependencies
|
|
||||||
|
|
||||||
[**Install Python build dependencies**](https://github.com/pyenv/pyenv/wiki#suggested-build-environment)
|
|
||||||
before attempting to install a new Python version.
|
|
||||||
|
|
||||||
You can now begin using Pyenv.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Install additional Python versions
|
|
||||||
|
|
||||||
To install additional Python versions, use [`pyenv install`](COMMANDS.md#pyenv-install).
|
|
||||||
|
|
||||||
For example, to download and install Python 3.10.4, run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pyenv install 3.10.4
|
|
||||||
```
|
|
||||||
|
|
||||||
Running `pyenv install -l` gives the list of all available versions.
|
|
||||||
|
|
||||||
**NOTE:** Most Pyenv-provided Python releases are source releases and are built
|
|
||||||
from source as part of installation (that's why you need Python build dependencies preinstalled).
|
|
||||||
You can pass options to Python's `configure` and compiler flags to customize the build,
|
|
||||||
see [_Special environment variables_ in Python-Build's README](plugins/python-build/README.md#special-environment-variables)
|
|
||||||
for details.
|
|
||||||
|
|
||||||
**NOTE:** If you are having trouble installing a Python version,
|
|
||||||
please visit the wiki page about
|
|
||||||
[Common Build Problems](https://github.com/pyenv/pyenv/wiki/Common-build-problems).
|
|
||||||
|
|
||||||
**NOTE:** If you want to use proxy for download, please set the `http_proxy` and `https_proxy`
|
|
||||||
environment variables.
|
|
||||||
|
|
||||||
**NOTE:** If you'd like a faster interpreter at the cost of longer build times,
|
|
||||||
see [_Building for maximum performance_ in Python-Build's README](plugins/python-build/README.md#building-for-maximum-performance).
|
|
||||||
|
|
||||||
|
|
||||||
#### Prefix auto-resolution to the latest version
|
|
||||||
|
|
||||||
All Pyenv subcommands except `uninstall` automatically resolve full prefixes to the latest version in the corresponding version line.
|
|
||||||
|
|
||||||
`pyenv install` picks the latest known version, while other subcommands pick the latest installed version.
|
|
||||||
|
|
||||||
E.g. to install and then switch to the latest 3.10 release:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pyenv install 3.10
|
|
||||||
pyenv global 3.10
|
|
||||||
```
|
|
||||||
|
|
||||||
You can run [`pyenv latest -k <prefix>`](COMMANDS.md#pyenv-latest) to see how `pyenv install` would resolve a specific prefix, or [`pyenv latest <prefix>`](COMMANDS.md#pyenv-latest) to see how other subcommands would resolve it.
|
|
||||||
|
|
||||||
See the [`pyenv latest` documentation](COMMANDS.md#pyenv-latest) for details.
|
|
||||||
|
|
||||||
|
|
||||||
#### Python versions with extended support
|
|
||||||
|
|
||||||
For the following Python releases, Pyenv applies user-provided patches that add support for some newer environments.
|
|
||||||
Though we don't actively maintain those patches, since existing releases never change,
|
|
||||||
it's safe to assume that they will continue working until there are further incompatible changes
|
|
||||||
in a later version of those environments.
|
|
||||||
|
|
||||||
* *3.7.8-3.7.15, 3.8.4-3.8.12, 3.9.0-3.9.7* : XCode 13.3
|
|
||||||
* *3.5.10, 3.6.15* : MacOS 11+ and XCode 13.3
|
|
||||||
* *2.7.18* : MacOS 10.15+ and Apple Silicon
|
|
||||||
|
|
||||||
|
|
||||||
### Switch between Python versions
|
|
||||||
|
|
||||||
To select a Pyenv-installed Python as the version to use, run one
|
|
||||||
of the following commands:
|
|
||||||
|
|
||||||
* [`pyenv shell <version>`](COMMANDS.md#pyenv-shell) -- select just for current shell session
|
|
||||||
* [`pyenv local <version>`](COMMANDS.md#pyenv-local) -- automatically select whenever you are in the current directory (or its subdirectories)
|
|
||||||
* [`pyenv global <version>`](COMMANDS.md#pyenv-shell) -- select globally for your user account
|
|
||||||
|
|
||||||
E.g. to select the above-mentioned newly-installed Python 3.10.4 as your preferred version to use:
|
|
||||||
|
|
||||||
~~~bash
|
|
||||||
pyenv global 3.10.4
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Now whenever you invoke `python`, `pip` etc., an executable from the Pyenv-provided
|
|
||||||
3.10.4 installation will be run instead of the system Python.
|
|
||||||
|
|
||||||
Using "`system`" as a version name would reset the selection to your system-provided Python.
|
|
||||||
|
|
||||||
See [Understanding shims](#understanding-shims) and
|
|
||||||
[Understanding Python version selection](#understanding-python-version-selection)
|
|
||||||
for more details on how the selection works and more information on its usage.
|
|
||||||
|
|
||||||
|
|
||||||
### Uninstall Python versions
|
|
||||||
|
|
||||||
As time goes on, you will accumulate Python versions in your
|
|
||||||
`$(pyenv root)/versions` directory.
|
|
||||||
|
|
||||||
To remove old Python versions, use [`pyenv uninstall <versions>`](COMMANDS.md#pyenv-uninstall).
|
|
||||||
|
|
||||||
Alternatively, you can simply `rm -rf` the directory of the version you want
|
|
||||||
to remove. You can find the directory of a particular Python version
|
|
||||||
with the `pyenv prefix` command, e.g. `pyenv prefix 2.6.8`.
|
|
||||||
Note however that plugins may run additional operations on uninstall
|
|
||||||
which you would need to do by hand as well. E.g. Pyenv-Virtualenv also
|
|
||||||
removes any virtual environments linked to the version being uninstalled.
|
|
||||||
|
|
||||||
|
|
||||||
### Other operations
|
|
||||||
|
|
||||||
Run `pyenv commands` to get a list of all available subcommands.
|
|
||||||
Run a subcommand with `--help` to get help on it, or see the [Commands Reference](COMMANDS.md).
|
|
||||||
|
|
||||||
Note that Pyenv plugins that you install may add their own subcommands.
|
|
||||||
|
|
||||||
|
|
||||||
## Upgrading
|
|
||||||
|
|
||||||
### Upgrading with Homebrew
|
|
||||||
|
|
||||||
If you've installed Pyenv using Homebrew, upgrade using:
|
|
||||||
```sh
|
|
||||||
brew upgrade pyenv
|
|
||||||
```
|
|
||||||
|
|
||||||
To switch from a release to the latest development head of Pyenv, use:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
brew uninstall pyenv
|
|
||||||
brew install pyenv --head
|
|
||||||
```
|
|
||||||
|
|
||||||
then you can upgrade it with `brew upgrade pyenv` as usual.
|
|
||||||
|
|
||||||
|
|
||||||
### Upgrading with Installer or Git checkout
|
|
||||||
|
|
||||||
If you've installed Pyenv with Pyenv-installer, you likely have the
|
|
||||||
[Pyenv-Update](https://github.com/pyenv/pyenv-update) plugin that would
|
|
||||||
upgrade Pyenv and all installed plugins:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pyenv update
|
|
||||||
```
|
|
||||||
|
|
||||||
If you've installed Pyenv using Pyenv-installer or Git checkout, you can also
|
|
||||||
upgrade your installation at any time using Git.
|
|
||||||
|
|
||||||
To upgrade to the latest development version of pyenv, use `git pull`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd $(pyenv root)
|
|
||||||
git pull
|
|
||||||
```
|
|
||||||
|
|
||||||
To upgrade to a specific release of Pyenv, check out the corresponding tag:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd $(pyenv root)
|
|
||||||
git fetch
|
|
||||||
git tag
|
|
||||||
git checkout v0.1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
## Uninstalling pyenv
|
|
||||||
|
|
||||||
The simplicity of pyenv makes it easy to temporarily disable it, or
|
|
||||||
uninstall from the system.
|
|
||||||
|
|
||||||
1. To **disable** Pyenv managing your Python versions, simply remove the
|
|
||||||
`pyenv init` invocations from your shell startup configuration. This will
|
|
||||||
remove Pyenv shims directory from `PATH`, and future invocations like
|
|
||||||
`python` will execute the system Python version, as it was before Pyenv.
|
|
||||||
|
|
||||||
`pyenv` will still be accessible on the command line, but your Python
|
|
||||||
apps won't be affected by version switching.
|
|
||||||
|
|
||||||
2. To completely **uninstall** Pyenv, remove _all_ Pyenv configuration lines
|
|
||||||
from your shell startup configuration, and then remove
|
|
||||||
its root directory. This will **delete all Python versions** that were
|
|
||||||
installed under the `` $(pyenv root)/versions/ `` directory:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
rm -rf $(pyenv root)
|
rbenv init
|
||||||
```
|
```
|
||||||
|
|
||||||
If you've installed Pyenv using a package manager, as a final step,
|
3. Close your Terminal window and open a new one so your changes take effect.
|
||||||
perform the Pyenv package removal. For instance, for Homebrew:
|
|
||||||
|
|
||||||
```
|
That's it! You are now ready to [install some Ruby versions](#installing-ruby-versions).
|
||||||
brew uninstall pyenv
|
|
||||||
|
### Basic Git Checkout
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> For a more automated install, you can use [rbenv-installer](https://github.com/rbenv/rbenv-installer#rbenv-installer). If you do not want to execute scripts downloaded from a web URL or simply prefer a manual approach, follow the steps below.
|
||||||
|
|
||||||
|
This will get you going with the latest version of rbenv without needing a system-wide install.
|
||||||
|
|
||||||
|
1. Clone rbenv into `~/.rbenv`.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
|
||||||
```
|
```
|
||||||
|
|
||||||
|
2. Set up your shell to load rbenv.
|
||||||
|
|
||||||
## Pyenv plugins
|
```sh
|
||||||
|
~/.rbenv/bin/rbenv init
|
||||||
|
```
|
||||||
|
|
||||||
Pyenv provides a simple, flexible and maintainable way to extend and customize its functionality with plugins --
|
If you are curious, see here to [understand what `init` does](#how-rbenv-hooks-into-your-shell).
|
||||||
as simple as creating a plugin directory and dropping a shell script on a certain subpath of it
|
|
||||||
with whatever extra logic you need to be run at certain moments.
|
|
||||||
|
|
||||||
See [_Plugins_ on the wiki](https://github.com/pyenv/pyenv/wiki/Plugins) on how to install and use plugins
|
3. Restart your shell so that these changes take effect. (Opening a new terminal tab will usually do it.)
|
||||||
as well as a catalog of some useful existing plugins for common needs.
|
|
||||||
|
|
||||||
See [_Authoring plugins_ on the wiki](https://github.com/pyenv/pyenv/wiki/Authoring-plugins) on writing your own plugins.
|
#### Shell completions
|
||||||
|
|
||||||
|
When _manually_ installing rbenv, it might be useful to note how completion scripts for various shells work. Completion scripts help with typing rbenv commands by expanding partially entered rbenv command names and option flags; typically this is invoked by pressing <kbd>Tab</kbd> key in an interactive shell.
|
||||||
|
|
||||||
## Advanced Configuration
|
- The **bash** completion script for rbenv ships with the project and gets [loaded by the `rbenv init` mechanism](#how-rbenv-hooks-into-your-shell).
|
||||||
|
|
||||||
Skip this section unless you must know what every line in your shell
|
- The **zsh** completion script ships with the project, but needs to be added to FPATH in zsh before it can be discovered by the shell. One way to do this would be to edit `~/.zshrc`:
|
||||||
profile is doing.
|
|
||||||
|
|
||||||
Also see the [Environment variables](#environment-variables) section
|
```sh
|
||||||
for the environment variables that control Pyenv's behavior.
|
# assuming that rbenv was installed to `~/.rbenv`
|
||||||
|
FPATH=~/.rbenv/completions:"$FPATH"
|
||||||
|
|
||||||
`pyenv init` is the only command that crosses the line of loading
|
autoload -U compinit
|
||||||
extra commands into your shell. Coming from RVM, some of you might be
|
compinit
|
||||||
opposed to this idea. Here's what `eval "$(pyenv init -)"` actually does:
|
```
|
||||||
|
|
||||||
|
- The **fish** completion script for rbenv ships with the fish shell itself and is not maintained by the rbenv project.
|
||||||
|
|
||||||
1. **Sets up the shims path.** This is what allows Pyenv to intercept
|
### Installing Ruby versions
|
||||||
and redirect invocations of `python`, `pip` etc. transparently.
|
|
||||||
It prepends `$(pyenv root)/shims` to your `$PATH`.
|
|
||||||
It also deletes any other instances of `$(pyenv root)/shims` on `PATH`
|
|
||||||
which allows to invoke `eval "$(pyenv init -)"` multiple times without
|
|
||||||
getting duplicate `PATH` entries.
|
|
||||||
|
|
||||||
2. **Installs autocompletion.** This is entirely optional but pretty
|
The `rbenv install` command does not ship with rbenv out-of-the-box, but is provided by the [ruby-build][] plugin.
|
||||||
useful. Sourcing `$(pyenv root)/completions/pyenv.bash` will set that
|
|
||||||
up. There are also completions for Zsh and Fish.
|
|
||||||
|
|
||||||
3. **Rehashes shims.** From time to time you'll need to rebuild your
|
Before attempting to install Ruby, **check that [your build environment](https://github.com/rbenv/ruby-build/wiki#suggested-build-environment) has the necessary tools and libraries**. Then:
|
||||||
shim files. Doing this on init makes sure everything is up to
|
|
||||||
date. You can always run `pyenv rehash` manually.
|
|
||||||
|
|
||||||
4. **Installs `pyenv` into the current shell as a shell function.**
|
```sh
|
||||||
This bit is also optional, but allows
|
# list latest stable versions:
|
||||||
pyenv and plugins to change variables in your current shell.
|
rbenv install -l
|
||||||
This is required for some commands like `pyenv shell` to work.
|
|
||||||
The sh dispatcher doesn't do
|
|
||||||
anything crazy like override `cd` or hack your shell prompt, but if
|
|
||||||
for some reason you need `pyenv` to be a real script rather than a
|
|
||||||
shell function, you can safely skip it.
|
|
||||||
|
|
||||||
`eval "$(pyenv init --path)"` only does items 1 and 3.
|
# list all local versions:
|
||||||
|
rbenv install -L
|
||||||
|
|
||||||
To see exactly what happens under the hood for yourself, run `pyenv init -`
|
# install a Ruby version:
|
||||||
or `pyenv init --path`.
|
rbenv install 3.1.2
|
||||||
|
```
|
||||||
|
|
||||||
`eval "$(pyenv init -)"` is supposed to run at any interactive shell's
|
For troubleshooting `BUILD FAILED` scenarios, check the [ruby-build Discussions section](https://github.com/rbenv/ruby-build/discussions/categories/build-failures).
|
||||||
startup (including nested shells -- e.g. those invoked from editors)
|
|
||||||
so that you get completion and convenience shell functions.
|
|
||||||
|
|
||||||
`eval "$(pyenv init --path)"` can be used instead of `eval "$(pyenv init -)"`
|
> [!NOTE]
|
||||||
to just enable shims, without shell integration. It can also be used to bump shims
|
> If the `rbenv install` command wasn't found, you can install ruby-build as a plugin:
|
||||||
to the front of `PATH` after some other logic has prepended stuff to `PATH`
|
> ```sh
|
||||||
that may shadow Pyenv's shims.
|
> git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
|
||||||
|
> ```
|
||||||
|
|
||||||
* In particular, in Debian-based distributions, the stock `~/.profile`
|
Set a Ruby version to finish installation and start using Ruby:
|
||||||
prepends per-user `bin` directories to `PATH` after having sourced `~/.bashrc`.
|
```sh
|
||||||
This necessitates appending a `pyenv init` call to `~/.profile` as well as `~/.bashrc`
|
rbenv global 3.1.2 # set the default Ruby version for this machine
|
||||||
in these distributions because the system's Pip places executables for
|
# or:
|
||||||
modules installed by a non-root user into those per-user `bin` directories.
|
rbenv local 3.1.2 # set the Ruby version for this directory
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively to the `rbenv install` command, you can download and compile Ruby manually as a subdirectory of `~/.rbenv/versions`. An entry in that directory can also be a symlink to a Ruby version installed elsewhere on the filesystem.
|
||||||
|
|
||||||
### Using Pyenv without shims
|
#### Installing Ruby gems
|
||||||
|
|
||||||
If you don't want to use `pyenv init` and shims, you can still benefit
|
Select a Ruby version for your project using `rbenv local 3.1.2`, for example. Then, proceed to install gems as you normally would:
|
||||||
from pyenv's ability to install Python versions for you. Just run
|
|
||||||
`pyenv install` and you will find versions installed in
|
|
||||||
`$(pyenv root)/versions`.
|
|
||||||
|
|
||||||
You can manually execute or symlink them as required,
|
```sh
|
||||||
or you can use [`pyenv exec <command>`](COMMANDS.md#pyenv-exec)
|
gem install bundler
|
||||||
whenever you want `<command>` to be affected by Pyenv's version selection
|
```
|
||||||
as currently configured.
|
|
||||||
|
|
||||||
`pyenv exec` works by prepending `$(pyenv root)/versions/<selected version>/bin`
|
> [!NOTE]
|
||||||
to `PATH` in the `<command>`'s environment, the same as what e.g. RVM does.
|
> You _should not use sudo_ to install gems. Typically, the Ruby versions will be installed under your home directory and thus writeable by your user. If you get the “you don't have write permissions” error when installing gems, it's likely that your "system" Ruby version is still a global default. Change that with `rbenv global <version>` and try again.
|
||||||
|
|
||||||
|
Check the location where gems are being installed with `gem env`:
|
||||||
|
|
||||||
### Environment variables
|
```sh
|
||||||
|
gem env home
|
||||||
|
# => ~/.rbenv/versions/<version>/lib/ruby/gems/...
|
||||||
|
```
|
||||||
|
|
||||||
You can affect how Pyenv operates with the following environment variables:
|
#### Uninstalling Ruby versions
|
||||||
|
|
||||||
|
As time goes on, Ruby versions you install will accumulate in your
|
||||||
|
`~/.rbenv/versions` directory.
|
||||||
|
|
||||||
|
To remove old Ruby versions, simply `rm -rf` the directory of the
|
||||||
|
version you want to remove. You can find the directory of a particular
|
||||||
|
Ruby version with the `rbenv prefix` command, e.g. `rbenv prefix
|
||||||
|
2.7.0`.
|
||||||
|
|
||||||
|
The [ruby-build][] plugin provides an `rbenv uninstall` command to
|
||||||
|
automate the removal process.
|
||||||
|
|
||||||
|
## Command Reference
|
||||||
|
|
||||||
|
The main rbenv commands you need to know are:
|
||||||
|
|
||||||
|
### rbenv versions
|
||||||
|
|
||||||
|
Lists all Ruby versions known to rbenv, and shows an asterisk next to
|
||||||
|
the currently active version.
|
||||||
|
|
||||||
|
$ rbenv versions
|
||||||
|
1.8.7-p352
|
||||||
|
1.9.2-p290
|
||||||
|
* 1.9.3-p327 (set by /Users/sam/.rbenv/version)
|
||||||
|
jruby-1.7.1
|
||||||
|
rbx-1.2.4
|
||||||
|
ree-1.8.7-2011.03
|
||||||
|
|
||||||
|
### rbenv version
|
||||||
|
|
||||||
|
Displays the currently active Ruby version, along with information on
|
||||||
|
how it was set.
|
||||||
|
|
||||||
|
$ rbenv version
|
||||||
|
1.9.3-p327 (set by /Users/sam/.rbenv/version)
|
||||||
|
|
||||||
|
### rbenv local
|
||||||
|
|
||||||
|
Sets a local application-specific Ruby version by writing the version
|
||||||
|
name to a `.ruby-version` file in the current directory. This version
|
||||||
|
overrides the global version, and can be overridden itself by setting
|
||||||
|
the `RBENV_VERSION` environment variable or with the `rbenv shell`
|
||||||
|
command.
|
||||||
|
|
||||||
|
rbenv local 3.1.2
|
||||||
|
|
||||||
|
When run without a version number, `rbenv local` reports the currently
|
||||||
|
configured local version. You can also unset the local version:
|
||||||
|
|
||||||
|
rbenv local --unset
|
||||||
|
|
||||||
|
### rbenv global
|
||||||
|
|
||||||
|
Sets the global version of Ruby to be used in all shells by writing
|
||||||
|
the version name to the `~/.rbenv/version` file. This version can be
|
||||||
|
overridden by an application-specific `.ruby-version` file, or by
|
||||||
|
setting the `RBENV_VERSION` environment variable.
|
||||||
|
|
||||||
|
rbenv global 3.1.2
|
||||||
|
|
||||||
|
The special version name `system` tells rbenv to use the system Ruby
|
||||||
|
(detected by searching your `$PATH`).
|
||||||
|
|
||||||
|
When run without a version number, `rbenv global` reports the
|
||||||
|
currently configured global version.
|
||||||
|
|
||||||
|
### rbenv shell
|
||||||
|
|
||||||
|
Sets a shell-specific Ruby version by setting the `RBENV_VERSION`
|
||||||
|
environment variable in your shell. This version overrides
|
||||||
|
application-specific versions and the global version.
|
||||||
|
|
||||||
|
rbenv shell jruby-1.7.1
|
||||||
|
|
||||||
|
When run without a version number, `rbenv shell` reports the current
|
||||||
|
value of `RBENV_VERSION`. You can also unset the shell version:
|
||||||
|
|
||||||
|
rbenv shell --unset
|
||||||
|
|
||||||
|
Note that you'll need rbenv's shell integration enabled (step 3 of
|
||||||
|
the installation instructions) in order to use this command. If you
|
||||||
|
prefer not to use shell integration, you may simply set the
|
||||||
|
`RBENV_VERSION` variable yourself:
|
||||||
|
|
||||||
|
export RBENV_VERSION=jruby-1.7.1
|
||||||
|
|
||||||
|
### rbenv rehash
|
||||||
|
|
||||||
|
Installs shims for all Ruby executables known to rbenv (`~/.rbenv/versions/*/bin/*`). Typically you do not need to run this command, as it will run automatically after installing gems.
|
||||||
|
|
||||||
|
rbenv rehash
|
||||||
|
|
||||||
|
### rbenv which
|
||||||
|
|
||||||
|
Displays the full path to the executable that rbenv will invoke when
|
||||||
|
you run the given command.
|
||||||
|
|
||||||
|
$ rbenv which irb
|
||||||
|
/Users/sam/.rbenv/versions/1.9.3-p327/bin/irb
|
||||||
|
|
||||||
|
### rbenv whence
|
||||||
|
|
||||||
|
Lists all Ruby versions that contain the specified executable name.
|
||||||
|
|
||||||
|
$ rbenv whence rackup
|
||||||
|
1.9.3-p327
|
||||||
|
jruby-1.7.1
|
||||||
|
ree-1.8.7-2011.03
|
||||||
|
|
||||||
|
## Environment variables
|
||||||
|
|
||||||
|
You can affect how rbenv operates with the following settings:
|
||||||
|
|
||||||
name | default | description
|
name | default | description
|
||||||
-----|---------|------------
|
-----|---------|------------
|
||||||
`PYENV_VERSION` | | Specifies the Python version to be used.<br>Also see [`pyenv shell`](COMMANDS.md#pyenv-shell)
|
`RBENV_VERSION` | | Specifies the Ruby version to be used.<br>Also see [`rbenv shell`](#rbenv-shell)
|
||||||
`PYENV_ROOT` | `~/.pyenv` | Defines the directory under which Python versions and shims reside.<br>Also see [`pyenv root`](COMMANDS.md#pyenv-root)
|
`RBENV_ROOT` | `~/.rbenv` | Defines the directory under which Ruby versions and shims reside.<br>Also see `rbenv root`
|
||||||
`PYENV_DEBUG` | | Outputs debug information.<br>Also as: `pyenv --debug <subcommand>`
|
`RBENV_DEBUG` | | Outputs debug information.<br>Also as: `rbenv --debug <subcommand>`
|
||||||
`PYENV_HOOK_PATH` | [_see wiki_][hooks] | Colon-separated list of paths searched for pyenv hooks.
|
`RBENV_HOOK_PATH` | [_see wiki_][hooks] | Colon-separated list of paths searched for rbenv hooks.
|
||||||
`PYENV_DIR` | `$PWD` | Directory to start searching for `.python-version` files.
|
`RBENV_DIR` | `$PWD` | Directory to start searching for `.ruby-version` files.
|
||||||
|
|
||||||
See also [_Special environment variables_ in Python-Build's README](plugins/python-build/README.md#special-environment-variables)
|
### How rbenv hooks into your shell
|
||||||
for environment variables that can be used to customize the build.
|
|
||||||
|
|
||||||
----
|
`rbenv init` is a helper command to hook rbenv into a shell. This helper is part of the recommended installation instructions, but optional, as an experienced user can set up the following tasks manually. The `rbenv init` command has two modes of operation:
|
||||||
|
|
||||||
|
1. `rbenv init`: made for humans, this command edits your shell initialization files on disk to add rbenv to shell startup. (Prior to rbenv 1.3.0, this mode only printed user instructions to the terminal, but did nothing else.)
|
||||||
|
|
||||||
|
2. `rbenv init -`: made for machines, this command outputs a shell script suitable to be eval'd by the user's shell.
|
||||||
|
|
||||||
|
When `rbenv init` is invoked from a bash shell, for example, it will add the following to the user's `~/.bashrc` or `~/.bash_profile`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Added by `rbenv init` on <DATE>
|
||||||
|
eval "$(rbenv init - --no-rehash bash)"
|
||||||
|
```
|
||||||
|
|
||||||
|
You may add this line to your shell initialization files manually if you want to avoid running `rbenv init` as part of the setup process. Here is what the eval'd script does:
|
||||||
|
|
||||||
|
0. Adds `rbenv` executable to PATH if necessary.
|
||||||
|
|
||||||
|
1. Prepends `~/.rbenv/shims` directory to PATH. This is basically the only requirement for rbenv to function properly.
|
||||||
|
|
||||||
|
2. Installs bash shell completion for rbenv commands.
|
||||||
|
|
||||||
|
3. Regenerates rbenv shims. If this step slows down your shell startup, you can invoke `rbenv init -` with the `--no-rehash` flag.
|
||||||
|
|
||||||
|
4. Installs the "sh" dispatcher. This bit is also optional, but allows rbenv and plugins to change variables in your current shell, making commands like `rbenv shell` possible.
|
||||||
|
|
||||||
|
|
||||||
|
### Uninstalling rbenv
|
||||||
|
|
||||||
|
The simplicity of rbenv makes it easy to temporarily disable it, or
|
||||||
|
uninstall from the system.
|
||||||
|
|
||||||
|
1. To **disable** rbenv managing your Ruby versions, simply comment or remove the `rbenv init` line from your shell startup configuration. This will remove rbenv shims directory from PATH, and future invocations like `ruby` will execute the system Ruby version, bypassing rbenv completely.
|
||||||
|
|
||||||
|
While disabled, `rbenv` will still be accessible on the command line, but your Ruby apps won't be affected by version switching.
|
||||||
|
|
||||||
|
2. To completely **uninstall** rbenv, perform step (1) and then remove the rbenv root directory. This will **delete all Ruby versions** that were installed under `` `rbenv root`/versions/ ``:
|
||||||
|
|
||||||
|
rm -rf "$(rbenv root)"
|
||||||
|
|
||||||
|
If you've installed rbenv using a package manager, as a final step
|
||||||
|
perform the rbenv package removal:
|
||||||
|
- Homebrew: `brew uninstall rbenv`
|
||||||
|
- Debian, Ubuntu, and their derivatives: `sudo apt purge rbenv`
|
||||||
|
- Archlinux and its derivatives: `sudo pacman -R rbenv`
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
The pyenv source code is [hosted on
|
|
||||||
GitHub](https://github.com/pyenv/pyenv). It's clean, modular,
|
|
||||||
and easy to understand, even if you're not a shell hacker.
|
|
||||||
|
|
||||||
Tests are executed using [Bats](https://github.com/bats-core/bats-core):
|
Tests are executed using [Bats](https://github.com/bats-core/bats-core):
|
||||||
|
|
||||||
bats test
|
$ bats test
|
||||||
bats/test/<file>.bats
|
$ bats test/<file>.bats
|
||||||
|
|
||||||
|
Please feel free to submit pull requests and file bugs on the [issue
|
||||||
|
tracker](https://github.com/rbenv/rbenv/issues).
|
||||||
|
|
||||||
|
|
||||||
### Contributing
|
[ruby-build]: https://github.com/rbenv/ruby-build#readme
|
||||||
|
[hooks]: https://github.com/rbenv/rbenv/wiki/Authoring-plugins#rbenv-hooks
|
||||||
Feel free to submit pull requests and file bugs on the [issue
|
[alternatives]: https://github.com/rbenv/rbenv/wiki/Comparison-of-version-managers
|
||||||
tracker](https://github.com/pyenv/pyenv/issues).
|
[plugins]: https://github.com/rbenv/rbenv/wiki/Plugins
|
||||||
|
|
||||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for more details on submitting changes.
|
|
||||||
|
|
||||||
|
|
||||||
### Version History
|
|
||||||
|
|
||||||
See [CHANGELOG.md](CHANGELOG.md).
|
|
||||||
|
|
||||||
|
|
||||||
### License
|
|
||||||
|
|
||||||
[The MIT License](LICENSE)
|
|
||||||
|
|
||||||
|
|
||||||
[pyenv-virtualenv]: https://github.com/pyenv/pyenv-virtualenv#readme
|
|
||||||
[hooks]: https://github.com/pyenv/pyenv/wiki/Authoring-plugins#pyenv-hooks
|
|
||||||
|
|||||||
13
completions/_rbenv
Normal file
13
completions/_rbenv
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#compdef rbenv
|
||||||
|
|
||||||
|
_rbenv() {
|
||||||
|
local completions
|
||||||
|
|
||||||
|
if [ "${#words}" -eq 2 ]; then
|
||||||
|
completions=(${(f)"$(rbenv help --complete-commands "${words[2]}")"})
|
||||||
|
_describe 'rbenv commands' completions
|
||||||
|
else
|
||||||
|
completions="$(rbenv completions ${words[2,-2]})"
|
||||||
|
compadd - "${(ps:\n:)completions}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
_pyenv() {
|
|
||||||
COMPREPLY=()
|
|
||||||
local word="${COMP_WORDS[COMP_CWORD]}"
|
|
||||||
|
|
||||||
if [ "$COMP_CWORD" -eq 1 ]; then
|
|
||||||
COMPREPLY=( $(compgen -W "$(pyenv commands)" -- "$word") )
|
|
||||||
else
|
|
||||||
local words=("${COMP_WORDS[@]}")
|
|
||||||
unset words[0]
|
|
||||||
unset words[$COMP_CWORD]
|
|
||||||
local completions=$(pyenv completions "${words[@]}")
|
|
||||||
COMPREPLY=( $(compgen -W "$completions" -- "$word") )
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
complete -F _pyenv pyenv
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
function __fish_pyenv_needs_command
|
|
||||||
set cmd (commandline -opc)
|
|
||||||
if [ (count $cmd) -eq 1 -a $cmd[1] = 'pyenv' ]
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function __fish_pyenv_using_command
|
|
||||||
set cmd (commandline -opc)
|
|
||||||
if [ (count $cmd) -gt 1 ]
|
|
||||||
if [ $argv[1] = $cmd[2] ]
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
complete -f -c pyenv -n '__fish_pyenv_needs_command' -a '(pyenv commands)'
|
|
||||||
for cmd in (pyenv commands)
|
|
||||||
complete -f -c pyenv -n "__fish_pyenv_using_command $cmd" -a \
|
|
||||||
"(pyenv completions (commandline -opc)[2..-1])"
|
|
||||||
end
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
if [[ ! -o interactive ]]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
compctl -K _pyenv pyenv
|
|
||||||
|
|
||||||
_pyenv() {
|
|
||||||
local words completions
|
|
||||||
read -cA words
|
|
||||||
|
|
||||||
if [ "${#words}" -eq 2 ]; then
|
|
||||||
completions="$(pyenv commands)"
|
|
||||||
else
|
|
||||||
completions="$(pyenv completions ${words[2,-2]})"
|
|
||||||
fi
|
|
||||||
|
|
||||||
reply=(${(ps:\n:)completions})
|
|
||||||
}
|
|
||||||
16
completions/rbenv.bash
Normal file
16
completions/rbenv.bash
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
_rbenv() {
|
||||||
|
COMPREPLY=()
|
||||||
|
local word="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
|
||||||
|
if [ "$COMP_CWORD" -eq 1 ]; then
|
||||||
|
COMPREPLY=( $(compgen -W "$(rbenv commands)" -- "$word") )
|
||||||
|
else
|
||||||
|
local words=("${COMP_WORDS[@]}")
|
||||||
|
unset "words[0]"
|
||||||
|
unset "words[$COMP_CWORD]"
|
||||||
|
local completions=$(rbenv completions "${words[@]}")
|
||||||
|
COMPREPLY=( $(compgen -W "$completions" -- "$word") )
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _rbenv rbenv
|
||||||
141
libexec/pyenv
141
libexec/pyenv
@@ -1,141 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ "$1" = "--debug" ]; then
|
|
||||||
export PYENV_DEBUG=1
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$PYENV_DEBUG" ]; then
|
|
||||||
# https://wiki-dev.bash-hackers.org/scripting/debuggingtips#making_xtrace_more_useful
|
|
||||||
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
|
|
||||||
abort() {
|
|
||||||
{ if [ "$#" -eq 0 ]; then cat -
|
|
||||||
else echo "pyenv: $*"
|
|
||||||
fi
|
|
||||||
} >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if enable -f "${BASH_SOURCE%/*}"/../libexec/pyenv-realpath.dylib realpath 2>/dev/null; then
|
|
||||||
abs_dirname() {
|
|
||||||
local path
|
|
||||||
path="$(realpath "$1")"
|
|
||||||
echo "${path%/*}"
|
|
||||||
}
|
|
||||||
else
|
|
||||||
[ -z "$PYENV_NATIVE_EXT" ] || abort "failed to load \`realpath' builtin"
|
|
||||||
|
|
||||||
READLINK=$(type -P readlink)
|
|
||||||
[ -n "$READLINK" ] || abort "cannot find readlink - are you missing GNU coreutils?"
|
|
||||||
|
|
||||||
resolve_link() {
|
|
||||||
$READLINK "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
abs_dirname() {
|
|
||||||
local path="$1"
|
|
||||||
|
|
||||||
# Use a subshell to avoid changing the current path
|
|
||||||
(
|
|
||||||
while [ -n "$path" ]; do
|
|
||||||
cd_path="${path%/*}"
|
|
||||||
if [[ "$cd_path" != "$path" ]]; then
|
|
||||||
cd "$cd_path"
|
|
||||||
fi
|
|
||||||
name="${path##*/}"
|
|
||||||
path="$(resolve_link "$name" || true)"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "$PWD"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${PYENV_ROOT}" ]; then
|
|
||||||
PYENV_ROOT="${HOME}/.pyenv"
|
|
||||||
else
|
|
||||||
PYENV_ROOT="${PYENV_ROOT%/}"
|
|
||||||
fi
|
|
||||||
export PYENV_ROOT
|
|
||||||
|
|
||||||
if [ -z "${PYENV_DIR}" ]; then
|
|
||||||
PYENV_DIR="$PWD"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d "$PYENV_DIR" ] || [ ! -e "$PYENV_DIR" ]; then
|
|
||||||
abort "cannot change working directory to \`$PYENV_DIR'"
|
|
||||||
fi
|
|
||||||
|
|
||||||
PYENV_DIR=$(cd "$PYENV_DIR" && echo "$PWD")
|
|
||||||
export PYENV_DIR
|
|
||||||
|
|
||||||
|
|
||||||
shopt -s nullglob
|
|
||||||
|
|
||||||
bin_path="$(abs_dirname "$0")"
|
|
||||||
for plugin_bin in "${bin_path%/*}"/plugins/*/bin; do
|
|
||||||
PATH="${plugin_bin}:${PATH}"
|
|
||||||
done
|
|
||||||
# PYENV_ROOT can be set to anything, so it may happen to be equal to the base path above,
|
|
||||||
# resulting in duplicate PATH entries
|
|
||||||
if [ "${bin_path%/*}" != "$PYENV_ROOT" ]; then
|
|
||||||
for plugin_bin in "${PYENV_ROOT}"/plugins/*/bin; do
|
|
||||||
PATH="${plugin_bin}:${PATH}"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
export PATH="${bin_path}:${PATH}"
|
|
||||||
|
|
||||||
PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:${PYENV_ROOT}/pyenv.d"
|
|
||||||
if [ "${bin_path%/*}" != "$PYENV_ROOT" ]; then
|
|
||||||
# Add pyenv's own `pyenv.d` unless pyenv was cloned to PYENV_ROOT
|
|
||||||
PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:${bin_path%/*}/pyenv.d"
|
|
||||||
fi
|
|
||||||
PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:/usr/local/etc/pyenv.d:/etc/pyenv.d:/usr/lib/pyenv/hooks"
|
|
||||||
for plugin_hook in "${PYENV_ROOT}/plugins/"*/etc/pyenv.d; do
|
|
||||||
PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:${plugin_hook}"
|
|
||||||
done
|
|
||||||
PYENV_HOOK_PATH="${PYENV_HOOK_PATH#:}"
|
|
||||||
export PYENV_HOOK_PATH
|
|
||||||
|
|
||||||
shopt -u nullglob
|
|
||||||
|
|
||||||
|
|
||||||
command="$1"
|
|
||||||
case "$command" in
|
|
||||||
"" )
|
|
||||||
{ pyenv---version
|
|
||||||
pyenv-help
|
|
||||||
} | abort
|
|
||||||
;;
|
|
||||||
-v | --version )
|
|
||||||
exec pyenv---version
|
|
||||||
;;
|
|
||||||
-h | --help )
|
|
||||||
exec pyenv-help
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
command_path="$(command -v "pyenv-$command" || true)"
|
|
||||||
if [ -z "$command_path" ]; then
|
|
||||||
if [ "$command" == "shell" ]; then
|
|
||||||
abort "shell integration not enabled. Run \`pyenv init' for instructions."
|
|
||||||
else
|
|
||||||
abort "no such command \`$command'"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
shift 1
|
|
||||||
if [ "$1" = --help ]; then
|
|
||||||
if [[ "$command" == "sh-"* ]]; then
|
|
||||||
echo "pyenv help \"$command\""
|
|
||||||
else
|
|
||||||
exec pyenv-help "$command"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
exec "$command_path" "$@"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: List all available pyenv commands
|
|
||||||
# Usage: pyenv commands [--sh|--no-sh]
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
echo --sh
|
|
||||||
echo --no-sh
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$1" = "--sh" ]; then
|
|
||||||
sh=1
|
|
||||||
shift
|
|
||||||
elif [ "$1" = "--no-sh" ]; then
|
|
||||||
nosh=1
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
IFS=: paths=($PATH)
|
|
||||||
|
|
||||||
shopt -s nullglob
|
|
||||||
|
|
||||||
{ for path in "${paths[@]}"; do
|
|
||||||
for command in "${path}/pyenv-"*; do
|
|
||||||
command="${command##*pyenv-}"
|
|
||||||
if [ -n "$sh" ]; then
|
|
||||||
if [ "${command:0:3}" = "sh-" ]; then
|
|
||||||
echo "${command##sh-}"
|
|
||||||
fi
|
|
||||||
elif [ -n "$nosh" ]; then
|
|
||||||
if [ "${command:0:3}" != "sh-" ]; then
|
|
||||||
echo "${command##sh-}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "${command##sh-}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
} | sort | uniq
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Usage: pyenv completions <command> [arg1 arg2...]
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
COMMAND="$1"
|
|
||||||
if [ -z "$COMMAND" ]; then
|
|
||||||
pyenv-help --usage completions >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$COMMAND" = "--complete" ]; then
|
|
||||||
exec pyenv-commands
|
|
||||||
fi
|
|
||||||
|
|
||||||
COMMAND_PATH="$(command -v "pyenv-$COMMAND" || command -v "pyenv-sh-$COMMAND")"
|
|
||||||
|
|
||||||
# --help is provided automatically
|
|
||||||
echo --help
|
|
||||||
|
|
||||||
if grep -iE "^([#%]|--|//) provide pyenv completions" "$COMMAND_PATH" >/dev/null; then
|
|
||||||
shift
|
|
||||||
exec "$COMMAND_PATH" --complete "$@"
|
|
||||||
fi
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Summary: Run an executable with the selected Python version
|
|
||||||
#
|
|
||||||
# Usage: pyenv exec <command> [arg1 arg2...]
|
|
||||||
#
|
|
||||||
# Runs an executable by first preparing PATH so that the selected Python
|
|
||||||
# version's `bin' directory is at the front.
|
|
||||||
#
|
|
||||||
# For example, if the currently selected Python version is 2.7.6:
|
|
||||||
# pyenv exec pip install -r requirements.txt
|
|
||||||
#
|
|
||||||
# is equivalent to:
|
|
||||||
# PATH="$PYENV_ROOT/versions/2.7.6/bin:$PATH" pip install -r requirements.txt
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
exec pyenv-shims --short
|
|
||||||
fi
|
|
||||||
|
|
||||||
PYENV_VERSION="$(pyenv-version-name)"
|
|
||||||
PYENV_COMMAND="$1"
|
|
||||||
|
|
||||||
if [ -z "$PYENV_COMMAND" ]; then
|
|
||||||
pyenv-help --usage exec >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
export PYENV_VERSION
|
|
||||||
PYENV_COMMAND_PATH="$(pyenv-which "$PYENV_COMMAND")"
|
|
||||||
PYENV_BIN_PATH="${PYENV_COMMAND_PATH%/*}"
|
|
||||||
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=$'\n' scripts=(`pyenv-hooks exec`)
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
for script in "${scripts[@]}"; do
|
|
||||||
source "$script"
|
|
||||||
done
|
|
||||||
|
|
||||||
shift 1
|
|
||||||
if [ "${PYENV_BIN_PATH#${PYENV_ROOT}}" != "${PYENV_BIN_PATH}" ]; then
|
|
||||||
# Only add to $PATH for non-system version.
|
|
||||||
export PATH="${PYENV_BIN_PATH}:${PATH}"
|
|
||||||
fi
|
|
||||||
exec "$PYENV_COMMAND_PATH" "$@"
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Summary: Set or show the global Python version(s)
|
|
||||||
#
|
|
||||||
# Usage: pyenv global <version> <version2> <..>
|
|
||||||
#
|
|
||||||
# Sets the global Python version(s). You can override the global version at
|
|
||||||
# any time by setting a directory-specific version with `pyenv local'
|
|
||||||
# or by setting the `PYENV_VERSION' environment variable.
|
|
||||||
#
|
|
||||||
# <version> can be specified multiple times and should be a version
|
|
||||||
# tag known to pyenv. The special version string `system' will use
|
|
||||||
# your default system Python. Run `pyenv versions' for a list of
|
|
||||||
# available Python versions.
|
|
||||||
#
|
|
||||||
# Example: To enable the python2.7 and python3.7 shims to find their
|
|
||||||
# respective executables you could set both versions with:
|
|
||||||
#
|
|
||||||
# 'pyenv global 3.7.0 2.7.15'
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
echo system
|
|
||||||
exec pyenv-versions --bare
|
|
||||||
fi
|
|
||||||
|
|
||||||
versions=("$@")
|
|
||||||
PYENV_VERSION_FILE="${PYENV_ROOT}/version"
|
|
||||||
|
|
||||||
if [ -n "$versions" ]; then
|
|
||||||
pyenv-version-file-write "$PYENV_VERSION_FILE" "${versions[@]}"
|
|
||||||
else
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=: versions=($(
|
|
||||||
pyenv-version-file-read "$PYENV_VERSION_FILE" ||
|
|
||||||
pyenv-version-file-read "${PYENV_ROOT}/global" ||
|
|
||||||
pyenv-version-file-read "${PYENV_ROOT}/default" ||
|
|
||||||
echo system
|
|
||||||
))
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
for version in "${versions[@]}"; do
|
|
||||||
echo "$version"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: List hook scripts for a given pyenv command
|
|
||||||
# Usage: pyenv hooks <command>
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
echo exec
|
|
||||||
echo rehash
|
|
||||||
echo version-name
|
|
||||||
echo version-origin
|
|
||||||
echo which
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
PYENV_COMMAND="$1"
|
|
||||||
if [ -z "$PYENV_COMMAND" ]; then
|
|
||||||
pyenv-help --usage hooks >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! enable -f "${BASH_SOURCE%/*}"/pyenv-realpath.dylib realpath 2>/dev/null; then
|
|
||||||
if [ -n "$PYENV_NATIVE_EXT" ]; then
|
|
||||||
echo "pyenv: failed to load \`realpath' builtin" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
READLINK=$(type -P readlink)
|
|
||||||
if [ -z "$READLINK" ]; then
|
|
||||||
echo "pyenv: cannot find readlink - are you missing GNU coreutils?" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
resolve_link() {
|
|
||||||
$READLINK "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
realpath() {
|
|
||||||
local path="$1"
|
|
||||||
local name
|
|
||||||
# Use a subshell to avoid changing the current path
|
|
||||||
(
|
|
||||||
while [ -n "$path" ]; do
|
|
||||||
name="${path##*/}"
|
|
||||||
[ "$name" = "$path" ] || cd "${path%/*}"
|
|
||||||
path="$(resolve_link "$name" || true)"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "${PWD}/$name"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
IFS=: hook_paths=($PYENV_HOOK_PATH)
|
|
||||||
|
|
||||||
shopt -s nullglob
|
|
||||||
for path in "${hook_paths[@]}"; do
|
|
||||||
for script in "$path/$PYENV_COMMAND"/*.bash; do
|
|
||||||
realpath "$script"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
shopt -u nullglob
|
|
||||||
@@ -1,312 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: Configure the shell environment for pyenv
|
|
||||||
# Usage: eval "$(pyenv init [-|--path] [--no-push-path] [--detect-shell] [--no-rehash] [<shell>])"
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
echo -
|
|
||||||
echo --path
|
|
||||||
echo --no-push-path
|
|
||||||
echo --no-rehash
|
|
||||||
echo --detect-shell
|
|
||||||
echo bash
|
|
||||||
echo fish
|
|
||||||
echo ksh
|
|
||||||
echo zsh
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
mode="help"
|
|
||||||
no_rehash=""
|
|
||||||
no_push_path=""
|
|
||||||
for args in "$@"
|
|
||||||
do
|
|
||||||
if [ "$args" = "-" ]; then
|
|
||||||
mode="print"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$args" = "--path" ]; then
|
|
||||||
mode="path"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$args" = "--detect-shell" ]; then
|
|
||||||
mode="detect-shell"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$args" = "--no-push-path" ]; then
|
|
||||||
no_push_path=1
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$args" = "--no-rehash" ]; then
|
|
||||||
no_rehash=1
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
shell="$1"
|
|
||||||
if [ -z "$shell" ]; then
|
|
||||||
shell="$(ps -p "$PPID" -o 'args=' 2>/dev/null || true)"
|
|
||||||
shell="${shell%% *}"
|
|
||||||
shell="${shell##-}"
|
|
||||||
shell="${shell:-$SHELL}"
|
|
||||||
shell="${shell##*/}"
|
|
||||||
shell="${shell%%-*}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
root="${0%/*}/.."
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
case "$mode" in
|
|
||||||
"help")
|
|
||||||
help_
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
"path")
|
|
||||||
print_path
|
|
||||||
print_rehash
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
"print")
|
|
||||||
init_dirs
|
|
||||||
print_path
|
|
||||||
print_env
|
|
||||||
print_completion
|
|
||||||
print_rehash
|
|
||||||
print_shell_function
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
"detect-shell")
|
|
||||||
detect_profile 1
|
|
||||||
print_detect_shell
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
# should never get here
|
|
||||||
exit 2
|
|
||||||
}
|
|
||||||
|
|
||||||
function detect_profile() {
|
|
||||||
local detect_for_detect_shell="$1"
|
|
||||||
|
|
||||||
case "$shell" in
|
|
||||||
bash )
|
|
||||||
if [ -e '~/.bash_profile' ]; then
|
|
||||||
profile='~/.bash_profile'
|
|
||||||
else
|
|
||||||
profile='~/.profile'
|
|
||||||
fi
|
|
||||||
profile_explain="~/.bash_profile if it exists, otherwise ~/.profile"
|
|
||||||
rc='~/.bashrc'
|
|
||||||
;;
|
|
||||||
zsh )
|
|
||||||
profile='~/.zprofile'
|
|
||||||
rc='~/.zshrc'
|
|
||||||
;;
|
|
||||||
ksh | ksh93 | mksh )
|
|
||||||
# There are two implementations of Korn shell: AT&T (ksh93) and Mir (mksh).
|
|
||||||
# Systems may have them installed under those names, or as ksh, so those
|
|
||||||
# are recognized here. The obsolete ksh88 (subsumed by ksh93) and pdksh
|
|
||||||
# (subsumed by mksh) are not included, since they are unlikely to still
|
|
||||||
# be in use as interactive shells anywhere.
|
|
||||||
profile='~/.profile'
|
|
||||||
rc='~/.profile'
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
if [ -n "$detect_for_detect_shell" ]; then
|
|
||||||
profile=
|
|
||||||
rc=
|
|
||||||
else
|
|
||||||
profile='your shell'\''s login startup file'
|
|
||||||
rc='your shell'\''s interactive startup file'
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_detect_shell() {
|
|
||||||
echo "PYENV_SHELL_DETECT=$shell"
|
|
||||||
echo "PYENV_PROFILE_DETECT=$profile"
|
|
||||||
echo "PYENV_RC_DETECT=$rc"
|
|
||||||
}
|
|
||||||
|
|
||||||
function help_() {
|
|
||||||
detect_profile
|
|
||||||
{
|
|
||||||
case "$shell" in
|
|
||||||
fish )
|
|
||||||
echo "# Add pyenv executable to PATH by running"
|
|
||||||
echo "# the following interactively:"
|
|
||||||
echo
|
|
||||||
echo 'set -Ux PYENV_ROOT $HOME/.pyenv'
|
|
||||||
echo 'set -U fish_user_paths $PYENV_ROOT/bin $fish_user_paths'
|
|
||||||
echo
|
|
||||||
echo "# Load pyenv automatically by appending"
|
|
||||||
echo "# the following to ~/.config/fish/config.fish:"
|
|
||||||
echo
|
|
||||||
echo 'pyenv init - | source'
|
|
||||||
echo
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
echo '# Load pyenv automatically by appending'
|
|
||||||
echo -n "# the following to "
|
|
||||||
if [ "$profile" == "$rc" ]; then
|
|
||||||
echo "$profile :"
|
|
||||||
else
|
|
||||||
echo
|
|
||||||
echo "# ${profile_explain:-$profile} (for login shells)"
|
|
||||||
echo "# and $rc (for interactive shells) :"
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
echo 'export PYENV_ROOT="$HOME/.pyenv"'
|
|
||||||
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"'
|
|
||||||
echo 'eval "$(pyenv init -)"'
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
echo
|
|
||||||
echo '# Restart your shell for the changes to take effect.'
|
|
||||||
echo
|
|
||||||
} >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
function init_dirs() {
|
|
||||||
mkdir -p "${PYENV_ROOT}/"{shims,versions}
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_path() {
|
|
||||||
# if no_push_path is set, guard the PATH manipulation with a check on whether
|
|
||||||
# the shim is already in the PATH.
|
|
||||||
if [ -n "$no_push_path" ]; then
|
|
||||||
case "$shell" in
|
|
||||||
fish )
|
|
||||||
echo 'if not contains -- "'"${PYENV_ROOT}/shims"'" $PATH'
|
|
||||||
print_path_prepend_shims
|
|
||||||
echo 'end'
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
echo 'if [[ ":$PATH:" != *'\':"${PYENV_ROOT}"/shims:\''* ]]; then'
|
|
||||||
print_path_prepend_shims
|
|
||||||
echo 'fi'
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
case "$shell" in
|
|
||||||
fish )
|
|
||||||
echo 'while set pyenv_index (contains -i -- "'"${PYENV_ROOT}/shims"'" $PATH)'
|
|
||||||
echo 'set -eg PATH[$pyenv_index]; end; set -e pyenv_index'
|
|
||||||
print_path_prepend_shims
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
# Some distros (notably Debian-based) set Bash's SSH_SOURCE_BASHRC compilation option
|
|
||||||
# that makes it source `bashrc` under SSH even when not interactive.
|
|
||||||
# This is inhibited by a guard in Debian's stock `bashrc` but some people remove it
|
|
||||||
# in order to get proper environment for noninteractive remote commands
|
|
||||||
# (SSH provides /etc/ssh/sshrc and ~/.ssh/rc for that but no-one seems to use them for some reason).
|
|
||||||
# This has caused an infinite `bashrc` execution loop for those people in the below nested Bash invocation (#2367).
|
|
||||||
# --norc negates this behavior of such a customized Bash.
|
|
||||||
echo 'PATH="$(bash --norc -ec '\''IFS=:; paths=($PATH); '
|
|
||||||
echo 'for i in ${!paths[@]}; do '
|
|
||||||
echo 'if [[ ${paths[i]} == "'\'\'"${PYENV_ROOT}/shims"\'\''" ]]; then unset '\'\\\'\''paths[i]'\'\\\'\''; '
|
|
||||||
echo 'fi; done; '
|
|
||||||
echo 'echo "${paths[*]}"'\'')"'
|
|
||||||
print_path_prepend_shims
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_path_prepend_shims() {
|
|
||||||
case "$shell" in
|
|
||||||
fish )
|
|
||||||
echo 'set -gx PATH '\'"${PYENV_ROOT}/shims"\'' $PATH'
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
echo 'export PATH="'"${PYENV_ROOT}"'/shims:${PATH}"'
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_env() {
|
|
||||||
case "$shell" in
|
|
||||||
fish )
|
|
||||||
echo "set -gx PYENV_SHELL $shell"
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
echo "export PYENV_SHELL=$shell"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_completion() {
|
|
||||||
completion="${root}/completions/pyenv.${shell}"
|
|
||||||
if [ -r "$completion" ]; then
|
|
||||||
echo "source '$completion'"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_rehash() {
|
|
||||||
if [ -z "$no_rehash" ]; then
|
|
||||||
echo 'command pyenv rehash 2>/dev/null'
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_shell_function() {
|
|
||||||
commands=(`pyenv-commands --sh`)
|
|
||||||
case "$shell" in
|
|
||||||
fish )
|
|
||||||
cat <<EOS
|
|
||||||
function pyenv
|
|
||||||
set command \$argv[1]
|
|
||||||
set -e argv[1]
|
|
||||||
|
|
||||||
switch "\$command"
|
|
||||||
case ${commands[*]}
|
|
||||||
source (pyenv "sh-\$command" \$argv|psub)
|
|
||||||
case '*'
|
|
||||||
command pyenv "\$command" \$argv
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
;;
|
|
||||||
ksh | ksh93 | mksh )
|
|
||||||
cat <<EOS
|
|
||||||
function pyenv {
|
|
||||||
typeset command
|
|
||||||
EOS
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
cat <<EOS
|
|
||||||
pyenv() {
|
|
||||||
local command
|
|
||||||
EOS
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ "$shell" != "fish" ]; then
|
|
||||||
IFS="|"
|
|
||||||
cat <<EOS
|
|
||||||
command="\${1:-}"
|
|
||||||
if [ "\$#" -gt 0 ]; then
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "\$command" in
|
|
||||||
${commands[*]:-/})
|
|
||||||
eval "\$(pyenv "sh-\$command" "\$@")"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
command pyenv "\$command" "\$@"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
EOS
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: Print the latest installed or known version with the given prefix
|
|
||||||
# Usage: pyenv latest [-k|--known] [-q|--quiet] <prefix>
|
|
||||||
#
|
|
||||||
# -k/--known Select from all known versions instead of installed
|
|
||||||
# -q/--quiet Do not print an error message on resolution failure
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]
|
|
||||||
do
|
|
||||||
case "$1" in
|
|
||||||
-k|--known)
|
|
||||||
FROM_KNOWN=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-q|--quiet)
|
|
||||||
QUIET=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
prefix=$1
|
|
||||||
exitcode=0
|
|
||||||
|
|
||||||
IFS=$'\n'
|
|
||||||
|
|
||||||
if [[ -z $FROM_KNOWN ]]; then
|
|
||||||
DEFINITION_CANDIDATES=( $(pyenv-versions --bare --skip-envs) )
|
|
||||||
else
|
|
||||||
DEFINITION_CANDIDATES=( $(python-build --definitions ) )
|
|
||||||
fi
|
|
||||||
|
|
||||||
if printf '%s\n' "${DEFINITION_CANDIDATES[@]}" 2>/dev/null | grep -qxFe "$prefix"; then
|
|
||||||
echo "$prefix"
|
|
||||||
exit $exitcode;
|
|
||||||
fi
|
|
||||||
|
|
||||||
# https://stackoverflow.com/questions/11856054/is-there-an-easy-way-to-pass-a-raw-string-to-grep/63483807#63483807
|
|
||||||
prefix_re="$(sed 's/[^\^]/[&]/g;s/[\^]/\\&/g' <<< "$prefix")"
|
|
||||||
# FIXME: more reliable and readable would probably be to loop over them and transform in pure Bash
|
|
||||||
DEFINITION_CANDIDATES=(\
|
|
||||||
$(printf '%s\n' "${DEFINITION_CANDIDATES[@]}" | \
|
|
||||||
grep -Ee "^$prefix_re[-.]" || true))
|
|
||||||
|
|
||||||
DEFINITION_CANDIDATES=(\
|
|
||||||
$(printf '%s\n' "${DEFINITION_CANDIDATES[@]}" | \
|
|
||||||
sed -E -e '/-dev$/d' -e '/-src$/d' -e '/-latest$/d' -e '/(a|b|rc)[0-9]+$/d'));
|
|
||||||
|
|
||||||
# Compose a sorting key, followed by | and original value
|
|
||||||
DEFINITION_CANDIDATES=(\
|
|
||||||
$(printf '%s\n' "${DEFINITION_CANDIDATES[@]}" | \
|
|
||||||
awk \
|
|
||||||
'{ if (match($0,"^[[:alnum:]]+-"))
|
|
||||||
{ print substr($0,0,RLENGTH-1) "." substr($0,RLENGTH+1) "..|" $0; }
|
|
||||||
else
|
|
||||||
{ print $0 "...|" $0; }
|
|
||||||
}'))
|
|
||||||
DEFINITION_CANDIDATES=(\
|
|
||||||
$(printf '%s\n' "${DEFINITION_CANDIDATES[@]}" \
|
|
||||||
| sort -t. -k1,1r -k 2,2nr -k 3,3nr -k4,4nr \
|
|
||||||
| cut -f2 -d $'|' \
|
|
||||||
|| true))
|
|
||||||
DEFINITION="${DEFINITION_CANDIDATES[0]}"
|
|
||||||
|
|
||||||
if [[ -n "$DEFINITION" ]]; then
|
|
||||||
echo "$DEFINITION"
|
|
||||||
else
|
|
||||||
if [[ -z $QUIET ]]; then
|
|
||||||
echo "pyenv: no $([[ -z $FROM_KNOWN ]] && echo installed || echo known) versions match the prefix \`$prefix'" >&2
|
|
||||||
fi
|
|
||||||
exitcode=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit $exitcode
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Summary: Set or show the local application-specific Python version(s)
|
|
||||||
#
|
|
||||||
# Usage: pyenv local <version> <version2> <..>
|
|
||||||
# pyenv local --unset
|
|
||||||
#
|
|
||||||
# Sets the local application-specific Python version(s) by writing the
|
|
||||||
# version name to a file named `.python-version'.
|
|
||||||
#
|
|
||||||
# When you run a Python command, pyenv will look for a `.python-version'
|
|
||||||
# file in the current directory and each parent directory. If no such
|
|
||||||
# file is found in the tree, pyenv will use the global Python version
|
|
||||||
# specified with `pyenv global'. A version specified with the
|
|
||||||
# `PYENV_VERSION' environment variable takes precedence over local
|
|
||||||
# and global versions.
|
|
||||||
#
|
|
||||||
# <version> can be specified multiple times and should be a version
|
|
||||||
# tag known to pyenv. The special version string `system' will use
|
|
||||||
# your default system Python. Run `pyenv versions' for a list of
|
|
||||||
# available Python versions.
|
|
||||||
#
|
|
||||||
# Example: To enable the python2.7 and python3.7 shims to find their
|
|
||||||
# respective executables you could set both versions with:
|
|
||||||
#
|
|
||||||
# 'pyenv local 3.7.0 2.7.15'
|
|
||||||
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
echo --unset
|
|
||||||
echo system
|
|
||||||
exec pyenv-versions --bare
|
|
||||||
fi
|
|
||||||
|
|
||||||
versions=("$@")
|
|
||||||
|
|
||||||
if [ "$versions" = "--unset" ]; then
|
|
||||||
rm -f .python-version
|
|
||||||
elif [ -n "$versions" ]; then
|
|
||||||
pyenv-version-file-write .python-version "${versions[@]}"
|
|
||||||
else
|
|
||||||
if version_file="$(pyenv-version-file "$PWD")"; then
|
|
||||||
IFS=: versions=($(pyenv-version-file-read "$version_file"))
|
|
||||||
for version in "${versions[@]}"; do
|
|
||||||
echo "$version"
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo "pyenv: no local version configured for this directory" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: Display prefixes for Python versions
|
|
||||||
# Usage: pyenv prefix [<version>...]
|
|
||||||
#
|
|
||||||
# Displays the directories where the given Python versions are installed,
|
|
||||||
# separated by colons. If no version is given, `pyenv prefix' displays the
|
|
||||||
# locations of the currently selected versions.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
echo system
|
|
||||||
exec pyenv-versions --bare
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$1" ]; then
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
{ IFS=:
|
|
||||||
export PYENV_VERSION="$*"
|
|
||||||
}
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
elif [ -z "$PYENV_VERSION" ]; then
|
|
||||||
PYENV_VERSION="$(pyenv-version-name)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
PYENV_PREFIX_PATHS=()
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
{ IFS=:
|
|
||||||
for version in ${PYENV_VERSION}; do
|
|
||||||
if [ "$version" = "system" ]; then
|
|
||||||
if PYTHON_PATH="$(PYENV_VERSION="${version}" pyenv-which python 2>/dev/null)" || \
|
|
||||||
PYTHON_PATH="$(PYENV_VERSION="${version}" pyenv-which python3 2>/dev/null)" || \
|
|
||||||
PYTHON_PATH="$(PYENV_VERSION="${version}" pyenv-which python2 2>/dev/null)"; then
|
|
||||||
shopt -s extglob
|
|
||||||
# In some distros (Arch), Python can be found in sbin as well as bin
|
|
||||||
PYENV_PREFIX_PATH="${PYTHON_PATH%/?(s)bin/*}"
|
|
||||||
PYENV_PREFIX_PATH="${PYENV_PREFIX_PATH:-/}"
|
|
||||||
else
|
|
||||||
echo "pyenv: system version not found in PATH" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
version="$(pyenv-latest -q "$version" || echo "$version")"
|
|
||||||
PYENV_PREFIX_PATH="${PYENV_ROOT}/versions/${version}"
|
|
||||||
fi
|
|
||||||
if [ -d "$PYENV_PREFIX_PATH" ]; then
|
|
||||||
PYENV_PREFIX_PATHS=("${PYENV_PREFIX_PATHS[@]}" "$PYENV_PREFIX_PATH")
|
|
||||||
else
|
|
||||||
echo "pyenv: version \`${version}' not installed" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
{ IFS=:
|
|
||||||
echo "${PYENV_PREFIX_PATHS[*]}"
|
|
||||||
}
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: Rehash pyenv shims (run this after installing executables)
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
SHIM_PATH="${PYENV_ROOT}/shims"
|
|
||||||
PROTOTYPE_SHIM_PATH="${SHIM_PATH}/.pyenv-shim"
|
|
||||||
|
|
||||||
# Create the shims directory if it doesn't already exist.
|
|
||||||
mkdir -p "$SHIM_PATH"
|
|
||||||
|
|
||||||
acquire_lock() {
|
|
||||||
# Ensure only one instance of pyenv-rehash is running at a time by
|
|
||||||
# setting the shell's `noclobber` option and attempting to write to
|
|
||||||
# the prototype shim file. If the file already exists, print a warning
|
|
||||||
# to stderr and exit with a non-zero status.
|
|
||||||
local ret
|
|
||||||
set -o noclobber
|
|
||||||
echo > "$PROTOTYPE_SHIM_PATH" 2>| /dev/null || ret=1
|
|
||||||
set +o noclobber
|
|
||||||
[ -z "${ret}" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
# If we were able to obtain a lock, register a trap to clean up the
|
|
||||||
# prototype shim when the process exits.
|
|
||||||
trap release_lock EXIT
|
|
||||||
|
|
||||||
remove_prototype_shim() {
|
|
||||||
rm -f "$PROTOTYPE_SHIM_PATH"
|
|
||||||
}
|
|
||||||
|
|
||||||
release_lock() {
|
|
||||||
remove_prototype_shim
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ ! -w "$SHIM_PATH" ]; then
|
|
||||||
echo "pyenv: cannot rehash: $SHIM_PATH isn't writable"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
unset acquired
|
|
||||||
start=$SECONDS
|
|
||||||
while (( SECONDS <= start + ${PYENV_REHASH_TIMEOUT:-60} )); do
|
|
||||||
if acquire_lock 2>/dev/null; then
|
|
||||||
acquired=1
|
|
||||||
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 "pyenv: cannot rehash: $PROTOTYPE_SHIM_PATH exists"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The prototype shim file is a script that re-execs itself, passing
|
|
||||||
# its filename and any arguments to `pyenv exec`. This file is
|
|
||||||
# hard-linked for every executable and then removed. The linking
|
|
||||||
# technique is fast, uses less disk space than unique files, and also
|
|
||||||
# serves as a locking mechanism.
|
|
||||||
create_prototype_shim() {
|
|
||||||
cat > "$PROTOTYPE_SHIM_PATH" <<SH
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -e
|
|
||||||
[ -n "\$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
program="\${0##*/}"
|
|
||||||
|
|
||||||
export PYENV_ROOT="$PYENV_ROOT"
|
|
||||||
exec "$(command -v pyenv)" exec "\$program" "\$@"
|
|
||||||
SH
|
|
||||||
chmod +x "$PROTOTYPE_SHIM_PATH"
|
|
||||||
}
|
|
||||||
|
|
||||||
# If the contents of the prototype shim file differ from the contents
|
|
||||||
# of the first shim in the shims directory, assume pyenv has been
|
|
||||||
# upgraded and the existing shims need to be removed.
|
|
||||||
remove_outdated_shims() {
|
|
||||||
local shim
|
|
||||||
for shim in "$SHIM_PATH"/*; do
|
|
||||||
if ! diff "$PROTOTYPE_SHIM_PATH" "$shim" >/dev/null 2>&1; then
|
|
||||||
rm -f "$SHIM_PATH"/*
|
|
||||||
fi
|
|
||||||
break
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# List basenames of executables for every Python version
|
|
||||||
list_executable_names() {
|
|
||||||
local version file
|
|
||||||
pyenv-versions --bare --skip-aliases | \
|
|
||||||
while read -r version; do
|
|
||||||
for file in "${PYENV_ROOT}/versions/${version}/bin/"*; do
|
|
||||||
echo "${file##*/}"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# The basename of each argument passed to `make_shims` will be
|
|
||||||
# registered for installation as a shim. In this way, plugins may call
|
|
||||||
# `make_shims` with a glob to register many shims at once.
|
|
||||||
make_shims() {
|
|
||||||
local file shim
|
|
||||||
for file; do
|
|
||||||
shim="${file##*/}"
|
|
||||||
register_shim "$shim"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((${BASH_VERSINFO[0]} > 3)); then
|
|
||||||
|
|
||||||
declare -A registered_shims
|
|
||||||
|
|
||||||
# Registers the name of a shim to be generated.
|
|
||||||
register_shim() {
|
|
||||||
registered_shims["$1"]=1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Install all shims registered via `make_shims` or `register_shim` directly.
|
|
||||||
install_registered_shims() {
|
|
||||||
local shim file
|
|
||||||
for shim in "${!registered_shims[@]}"; do
|
|
||||||
file="${SHIM_PATH}/${shim}"
|
|
||||||
[ -e "$file" ] || cp "$PROTOTYPE_SHIM_PATH" "$file"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Once the registered shims have been installed, we make a second pass
|
|
||||||
# over the contents of the shims directory. Any file that is present
|
|
||||||
# in the directory but has not been registered as a shim should be
|
|
||||||
# removed.
|
|
||||||
remove_stale_shims() {
|
|
||||||
local shim
|
|
||||||
for shim in "$SHIM_PATH"/*; do
|
|
||||||
if [[ ! ${registered_shims["${shim##*/}"]} ]]; then
|
|
||||||
rm -f "$shim"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
else # Same for bash < 4.
|
|
||||||
|
|
||||||
registered_shims=" "
|
|
||||||
|
|
||||||
register_shim() {
|
|
||||||
registered_shims="${registered_shims}${1} "
|
|
||||||
}
|
|
||||||
|
|
||||||
install_registered_shims() {
|
|
||||||
local shim file
|
|
||||||
for shim in $registered_shims; do
|
|
||||||
file="${SHIM_PATH}/${shim}"
|
|
||||||
[ -e "$file" ] || cp "$PROTOTYPE_SHIM_PATH" "$file"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_stale_shims() {
|
|
||||||
local shim
|
|
||||||
for shim in "$SHIM_PATH"/*; do
|
|
||||||
if [[ "$registered_shims" != *" ${shim##*/} "* ]]; then
|
|
||||||
rm -f "$shim"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
shopt -s nullglob
|
|
||||||
|
|
||||||
# Create the prototype shim, then register shims for all known
|
|
||||||
# executables.
|
|
||||||
create_prototype_shim
|
|
||||||
remove_outdated_shims
|
|
||||||
# shellcheck disable=SC2046
|
|
||||||
make_shims $(list_executable_names | sort -u)
|
|
||||||
|
|
||||||
|
|
||||||
# Allow plugins to register shims.
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=$'\n' scripts=(`pyenv-hooks rehash`)
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
|
|
||||||
for script in "${scripts[@]}"; do
|
|
||||||
source "$script"
|
|
||||||
done
|
|
||||||
|
|
||||||
install_registered_shims
|
|
||||||
remove_stale_shims
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Summary: Set or show the shell-specific Python version
|
|
||||||
#
|
|
||||||
# Usage: pyenv shell <version>...
|
|
||||||
# pyenv shell -
|
|
||||||
# pyenv shell --unset
|
|
||||||
#
|
|
||||||
# Sets a shell-specific Python version by setting the `PYENV_VERSION'
|
|
||||||
# environment variable in your shell. This version overrides local
|
|
||||||
# application-specific versions and the global version.
|
|
||||||
#
|
|
||||||
# <version> should be a string matching a Python version known to pyenv.
|
|
||||||
# The special version string `system' will use your default system Python.
|
|
||||||
# Run `pyenv versions' for a list of available Python versions.
|
|
||||||
#
|
|
||||||
# When `-` is passed instead of the version string, the previously set
|
|
||||||
# version will be restored. With `--unset`, the `PYENV_VERSION`
|
|
||||||
# environment variable gets unset, restoring the environment to the
|
|
||||||
# state before the first `pyenv shell` call.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
echo --unset
|
|
||||||
echo system
|
|
||||||
exec pyenv-versions --bare
|
|
||||||
fi
|
|
||||||
|
|
||||||
versions=("$@")
|
|
||||||
shell="$(basename "${PYENV_SHELL:-$SHELL}")"
|
|
||||||
|
|
||||||
if [ -z "$versions" ]; then
|
|
||||||
if [ -z "$PYENV_VERSION" ]; then
|
|
||||||
echo "pyenv: no shell-specific version configured" >&2
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo 'echo "$PYENV_VERSION"'
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$versions" = "--unset" ]; then
|
|
||||||
case "$shell" in
|
|
||||||
fish )
|
|
||||||
echo 'set -gu PYENV_VERSION_OLD "$PYENV_VERSION"'
|
|
||||||
echo "set -e PYENV_VERSION"
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
echo 'PYENV_VERSION_OLD="${PYENV_VERSION-}"'
|
|
||||||
echo "unset PYENV_VERSION"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$versions" = "-" ]; then
|
|
||||||
case "$shell" in
|
|
||||||
fish )
|
|
||||||
cat <<EOS
|
|
||||||
if set -q PYENV_VERSION_OLD
|
|
||||||
if [ -n "\$PYENV_VERSION_OLD" ]
|
|
||||||
set PYENV_VERSION_OLD_ "\$PYENV_VERSION"
|
|
||||||
set -gx PYENV_VERSION "\$PYENV_VERSION_OLD"
|
|
||||||
set -gu PYENV_VERSION_OLD "\$PYENV_VERSION_OLD_"
|
|
||||||
set -e PYENV_VERSION_OLD_
|
|
||||||
else
|
|
||||||
set -gu PYENV_VERSION_OLD "\$PYENV_VERSION"
|
|
||||||
set -e PYENV_VERSION
|
|
||||||
end
|
|
||||||
else
|
|
||||||
echo "pyenv: PYENV_VERSION_OLD is not set" >&2
|
|
||||||
false
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
cat <<EOS
|
|
||||||
if [ -n "\${PYENV_VERSION_OLD+x}" ]; then
|
|
||||||
if [ -n "\$PYENV_VERSION_OLD" ]; then
|
|
||||||
PYENV_VERSION_OLD_="\$PYENV_VERSION"
|
|
||||||
export PYENV_VERSION="\$PYENV_VERSION_OLD"
|
|
||||||
PYENV_VERSION_OLD="\$PYENV_VERSION_OLD_"
|
|
||||||
unset PYENV_VERSION_OLD_
|
|
||||||
else
|
|
||||||
PYENV_VERSION_OLD="\$PYENV_VERSION"
|
|
||||||
unset PYENV_VERSION
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "pyenv: PYENV_VERSION_OLD is not set" >&2
|
|
||||||
false
|
|
||||||
fi
|
|
||||||
EOS
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make sure the specified version is installed.
|
|
||||||
if pyenv-prefix "${versions[@]}" >/dev/null; then
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=: version="${versions[*]}"
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
if [ "$version" != "$PYENV_VERSION" ]; then
|
|
||||||
case "$shell" in
|
|
||||||
fish )
|
|
||||||
echo 'set -gu PYENV_VERSION_OLD "$PYENV_VERSION"'
|
|
||||||
echo "set -gx PYENV_VERSION \"$version\""
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
echo 'PYENV_VERSION_OLD="${PYENV_VERSION-}"'
|
|
||||||
echo "export PYENV_VERSION=\"${version}\""
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "false"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: Show the current Python version(s) and its origin
|
|
||||||
#
|
|
||||||
# Shows the currently selected Python version(s) and how it was
|
|
||||||
# selected. To obtain only the version string, use `pyenv
|
|
||||||
# version-name'.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
exitcode=0
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=: PYENV_VERSION_NAMES=($(pyenv-version-name)) || exitcode=$?
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
|
|
||||||
for PYENV_VERSION_NAME in "${PYENV_VERSION_NAMES[@]}"; do
|
|
||||||
echo "$PYENV_VERSION_NAME (set by $(pyenv-version-origin))"
|
|
||||||
done
|
|
||||||
|
|
||||||
exit $exitcode
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Usage: pyenv version-file [<dir>]
|
|
||||||
# Summary: Detect the file that sets the current pyenv version
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
target_dir="$1"
|
|
||||||
|
|
||||||
find_local_version_file() {
|
|
||||||
local root="$1"
|
|
||||||
while ! [[ "$root" =~ ^//[^/]*$ ]]; do
|
|
||||||
if [ -f "${root}/.python-version" ]; then
|
|
||||||
echo "${root}/.python-version"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
[ -n "$root" ] || break
|
|
||||||
root="${root%/*}"
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ -n "$target_dir" ]; then
|
|
||||||
find_local_version_file "$target_dir"
|
|
||||||
else
|
|
||||||
find_local_version_file "$PYENV_DIR" || {
|
|
||||||
[ "$PYENV_DIR" != "$PWD" ] && find_local_version_file "$PWD"
|
|
||||||
} || echo "${PYENV_ROOT}/version"
|
|
||||||
fi
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Usage: pyenv version-file-read <file>
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
VERSION_FILE="$1"
|
|
||||||
|
|
||||||
function is_version_safe() {
|
|
||||||
# As needed, check that the constructed path exists as a child path of PYENV_ROOT/versions
|
|
||||||
version="$1"
|
|
||||||
if [[ "$version" == ".." || "$version" == */* ]]; then
|
|
||||||
# Sanity check the value of version to prevent malicious path-traversal
|
|
||||||
(
|
|
||||||
cd "$PYENV_ROOT/versions/$version" &>/dev/null || exit 1
|
|
||||||
[[ "$PWD" == "$PYENV_ROOT/versions/"* ]]
|
|
||||||
)
|
|
||||||
return $?
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ -s "$VERSION_FILE" ]; then
|
|
||||||
# Read the first non-whitespace word from the specified version file.
|
|
||||||
# Be careful not to load it whole in case there's something crazy in it.
|
|
||||||
IFS="$IFS"$'\r'
|
|
||||||
sep=
|
|
||||||
while read -n 1024 -r version _ || [[ $version ]]; do
|
|
||||||
if [[ -z "$version" || "$version" == \#* ]]; then
|
|
||||||
# Skip empty lines and comments
|
|
||||||
continue
|
|
||||||
elif ! is_version_safe "$version"; then
|
|
||||||
# CVE-2022-35861 allowed arbitrary code execution in some contexts and is mitigated by is_version_safe.
|
|
||||||
echo "pyenv: invalid version \`$version' ignored in \`$VERSION_FILE'" >&2
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
printf "%s%s" "$sep" "$version"
|
|
||||||
sep=:
|
|
||||||
done <"$VERSION_FILE"
|
|
||||||
[[ $sep ]] && { echo; exit; }
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 1
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Usage: pyenv version-file-write <file> <version>
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
PYENV_VERSION_FILE="$1"
|
|
||||||
shift || true
|
|
||||||
versions=("$@")
|
|
||||||
|
|
||||||
if [ -z "$versions" ] || [ -z "$PYENV_VERSION_FILE" ]; then
|
|
||||||
pyenv-help --usage version-file-write >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make sure the specified version is installed.
|
|
||||||
pyenv-prefix "${versions[@]}" >/dev/null
|
|
||||||
|
|
||||||
# Write the version out to disk.
|
|
||||||
# Create an empty file. Using "rm" might cause a permission error.
|
|
||||||
> "$PYENV_VERSION_FILE"
|
|
||||||
for version in "${versions[@]}"; do
|
|
||||||
echo "$version" >> "$PYENV_VERSION_FILE"
|
|
||||||
done
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: Show the current Python version
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
if [ -z "$PYENV_VERSION" ]; then
|
|
||||||
PYENV_VERSION_FILE="$(pyenv-version-file)"
|
|
||||||
PYENV_VERSION="$(pyenv-version-file-read "$PYENV_VERSION_FILE" || true)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=$'\n' scripts=(`pyenv-hooks version-name`)
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
for script in "${scripts[@]}"; do
|
|
||||||
source "$script"
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$PYENV_VERSION" ] || [ "$PYENV_VERSION" = "system" ]; then
|
|
||||||
echo "system"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
version_exists() {
|
|
||||||
local version="$1"
|
|
||||||
[ -d "${PYENV_ROOT}/versions/${version}" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
versions=()
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
{ IFS=:
|
|
||||||
any_not_installed=0
|
|
||||||
for version in ${PYENV_VERSION}; do
|
|
||||||
if version_exists "$version" || [ "$version" = "system" ]; then
|
|
||||||
versions=("${versions[@]}" "${version}")
|
|
||||||
elif version_exists "${version#python-}"; then
|
|
||||||
versions=("${versions[@]}" "${version#python-}")
|
|
||||||
elif resolved_version="$(pyenv-latest -q "$version")"; then
|
|
||||||
versions=("${versions[@]}" "${resolved_version}")
|
|
||||||
else
|
|
||||||
echo "pyenv: version \`$version' is not installed (set by $(pyenv-version-origin))" >&2
|
|
||||||
any_not_installed=1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
{ IFS=:
|
|
||||||
echo "${versions[*]}"
|
|
||||||
}
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
|
|
||||||
if [ "$any_not_installed" = 1 ]; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: Explain how the current Python version is set
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
unset PYENV_VERSION_ORIGIN
|
|
||||||
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=$'\n' scripts=(`pyenv-hooks version-origin`)
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
for script in "${scripts[@]}"; do
|
|
||||||
source "$script"
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -n "$PYENV_VERSION_ORIGIN" ]; then
|
|
||||||
echo "$PYENV_VERSION_ORIGIN"
|
|
||||||
elif [ -n "$PYENV_VERSION" ]; then
|
|
||||||
echo "PYENV_VERSION environment variable"
|
|
||||||
else
|
|
||||||
pyenv-version-file
|
|
||||||
fi
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: List all Python versions available to pyenv
|
|
||||||
# Usage: pyenv versions [--bare] [--skip-aliases] [--skip-envs]
|
|
||||||
#
|
|
||||||
# Lists all Python versions found in `$PYENV_ROOT/versions/*'.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
unset bare skip_aliases skip_envs
|
|
||||||
# Provide pyenv completions
|
|
||||||
for arg; do
|
|
||||||
case "$arg" in
|
|
||||||
--complete )
|
|
||||||
echo --bare
|
|
||||||
echo --skip-aliases
|
|
||||||
echo --skip-envs
|
|
||||||
exit ;;
|
|
||||||
--bare ) bare=1 ;;
|
|
||||||
--skip-aliases ) skip_aliases=1 ;;
|
|
||||||
--skip-envs ) skip_envs=1 ;;
|
|
||||||
* )
|
|
||||||
pyenv-help --usage versions >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
versions_dir="${PYENV_ROOT}/versions"
|
|
||||||
|
|
||||||
if ! enable -f "${BASH_SOURCE%/*}"/pyenv-realpath.dylib realpath 2>/dev/null; then
|
|
||||||
if [ -n "$PYENV_NATIVE_EXT" ]; then
|
|
||||||
echo "pyenv: failed to load \`realpath' builtin" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
READLINK=$(type -P readlink)
|
|
||||||
if [ -z "$READLINK" ]; then
|
|
||||||
echo "pyenv: cannot find readlink - are you missing GNU coreutils?" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
resolve_link() {
|
|
||||||
$READLINK "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
realpath() {
|
|
||||||
local path="$1"
|
|
||||||
local name
|
|
||||||
|
|
||||||
# Use a subshell to avoid changing the current path
|
|
||||||
(
|
|
||||||
while [ -n "$path" ]; do
|
|
||||||
name="${path##*/}"
|
|
||||||
[ "$name" = "$path" ] || cd "${path%/*}"
|
|
||||||
path="$(resolve_link "$name" || true)"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "${PWD}/$name"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "$versions_dir" ]; then
|
|
||||||
versions_dir="$(realpath "$versions_dir")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ((${BASH_VERSINFO[0]} > 3)); then
|
|
||||||
declare -A current_versions
|
|
||||||
else
|
|
||||||
current_versions=()
|
|
||||||
fi
|
|
||||||
if [ -n "$bare" ]; then
|
|
||||||
include_system=""
|
|
||||||
else
|
|
||||||
hit_prefix="* "
|
|
||||||
miss_prefix=" "
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=:
|
|
||||||
if ((${BASH_VERSINFO[0]} > 3)); then
|
|
||||||
for i in $(pyenv-version-name || true); do
|
|
||||||
current_versions["$i"]="1"
|
|
||||||
done
|
|
||||||
else
|
|
||||||
current_versions=($(pyenv-version-name || true))
|
|
||||||
fi
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
include_system="1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
num_versions=0
|
|
||||||
|
|
||||||
exists() {
|
|
||||||
local car="$1"
|
|
||||||
local cdar
|
|
||||||
shift
|
|
||||||
for cdar in "$@"; do
|
|
||||||
if [ "${car}" == "${cdar}" ]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
print_version() {
|
|
||||||
local version="${1:?}"
|
|
||||||
if [[ -n $bare ]]; then
|
|
||||||
echo "$version"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
local path="${2:?}"
|
|
||||||
if [[ -L "$path" ]]; then
|
|
||||||
# Only resolve the link itself for printing, do not resolve further.
|
|
||||||
# Doing otherwise would misinform the user of what the link contains.
|
|
||||||
version_repr="$version --> $(readlink "$path")"
|
|
||||||
else
|
|
||||||
version_repr="$version"
|
|
||||||
fi
|
|
||||||
if [[ ${BASH_VERSINFO[0]} -ge 4 && ${current_versions["$1"]} ]]; then
|
|
||||||
echo "${hit_prefix}${version_repr} (set by $(pyenv-version-origin))"
|
|
||||||
elif (( ${BASH_VERSINFO[0]} <= 3 )) && exists "$1" "${current_versions[@]}"; then
|
|
||||||
echo "${hit_prefix}${version_repr} (set by $(pyenv-version-origin))"
|
|
||||||
else
|
|
||||||
echo "${miss_prefix}${version_repr}"
|
|
||||||
fi
|
|
||||||
num_versions=$((num_versions + 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
# Include "system" in the non-bare output, if it exists
|
|
||||||
if [ -n "$include_system" ] && \
|
|
||||||
(PYENV_VERSION=system pyenv-which python >/dev/null 2>&1 || \
|
|
||||||
PYENV_VERSION=system pyenv-which python3 >/dev/null 2>&1 || \
|
|
||||||
PYENV_VERSION=system pyenv-which python2 >/dev/null 2>&1) ; then
|
|
||||||
print_version system "/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
shopt -s dotglob nullglob
|
|
||||||
versions_dir_entries=("$versions_dir"/*)
|
|
||||||
if sort --version-sort </dev/null >/dev/null 2>&1; then
|
|
||||||
# system sort supports version sorting
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=$'\n'
|
|
||||||
versions_dir_entries=($(
|
|
||||||
printf "%s\n" "${versions_dir_entries[@]}" |
|
|
||||||
sort --version-sort
|
|
||||||
))
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
for path in "${versions_dir_entries[@]}"; do
|
|
||||||
if [ -d "$path" ]; then
|
|
||||||
if [ -n "$skip_aliases" ] && [ -L "$path" ]; then
|
|
||||||
target="$(realpath "$path")"
|
|
||||||
[ "${target%/*}" == "$versions_dir" ] && continue
|
|
||||||
[ "${target%/*/envs/*}" == "$versions_dir" ] && continue
|
|
||||||
fi
|
|
||||||
print_version "${path##*/}" "$path"
|
|
||||||
# virtual environments created by anaconda/miniconda/pyenv-virtualenv
|
|
||||||
if [[ -z $skip_envs ]]; then
|
|
||||||
for env_path in "${path}/envs/"*; do
|
|
||||||
if [ -d "${env_path}" ]; then
|
|
||||||
print_version "${env_path#${PYENV_ROOT}/versions/}" "${env_path}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
shopt -u dotglob nullglob
|
|
||||||
|
|
||||||
if [ "$num_versions" -eq 0 ] && [ -n "$include_system" ]; then
|
|
||||||
echo "Warning: no Python detected on the system" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Summary: List all Python versions that contain the given executable
|
|
||||||
# Usage: pyenv whence [--path] <command>
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
echo --path
|
|
||||||
exec pyenv-shims --short
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$1" = "--path" ]; then
|
|
||||||
print_paths="1"
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
print_paths=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
whence() {
|
|
||||||
local command="$1"
|
|
||||||
pyenv-versions --bare | while read -r version; do
|
|
||||||
path="$(pyenv-prefix "$version")/bin/${command}"
|
|
||||||
if [ -x "$path" ]; then
|
|
||||||
[ "$print_paths" ] && echo "$path" || echo "$version"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
PYENV_COMMAND="$1"
|
|
||||||
if [ -z "$PYENV_COMMAND" ]; then
|
|
||||||
pyenv-help --usage whence >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
result="$(whence "$PYENV_COMMAND")"
|
|
||||||
[ -n "$result" ] && echo "$result"
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Summary: Display the full path to an executable
|
|
||||||
#
|
|
||||||
# Usage: pyenv which <command> [--nosystem]
|
|
||||||
#
|
|
||||||
# Displays the full path to the executable that pyenv will invoke when
|
|
||||||
# you run the given command.
|
|
||||||
# Use --nosystem argument in case when you don't need to search command in the
|
|
||||||
# system environment.
|
|
||||||
#
|
|
||||||
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
exec pyenv-shims --short
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$2" = "--nosystem" ]; then
|
|
||||||
system=""
|
|
||||||
else
|
|
||||||
system="system"
|
|
||||||
fi
|
|
||||||
|
|
||||||
remove_from_path() {
|
|
||||||
local path_to_remove="$1"
|
|
||||||
local path_before
|
|
||||||
local result=":${PATH//\~/$HOME}:"
|
|
||||||
while [ "$path_before" != "$result" ]; do
|
|
||||||
path_before="$result"
|
|
||||||
result="${result//:$path_to_remove:/:}"
|
|
||||||
done
|
|
||||||
result="${result%:}"
|
|
||||||
echo "${result#:}"
|
|
||||||
}
|
|
||||||
|
|
||||||
PYENV_COMMAND="$1"
|
|
||||||
|
|
||||||
if [ -z "$PYENV_COMMAND" ]; then
|
|
||||||
pyenv-help --usage which >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=: versions=(${PYENV_VERSION:-$(pyenv-version-name)})
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
|
|
||||||
declare -a nonexistent_versions
|
|
||||||
|
|
||||||
for version in "${versions[@]}" "$system"; do
|
|
||||||
if [ "$version" = "system" ]; then
|
|
||||||
PATH="$(remove_from_path "${PYENV_ROOT}/shims")"
|
|
||||||
PYENV_COMMAND_PATH="$(command -v "$PYENV_COMMAND" || true)"
|
|
||||||
else
|
|
||||||
# $version may be a prefix to be resolved by pyenv-latest
|
|
||||||
version_path="$(pyenv-prefix "${version}" 2>/dev/null)" || \
|
|
||||||
{ nonexistent_versions+=("$version"); continue; }
|
|
||||||
# resolve $version for hooks
|
|
||||||
version="$(basename "$version_path")"
|
|
||||||
PYENV_COMMAND_PATH="$version_path/bin/${PYENV_COMMAND}"
|
|
||||||
unset version_path
|
|
||||||
fi
|
|
||||||
if [ -x "$PYENV_COMMAND_PATH" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=$'\n' scripts=(`pyenv-hooks which`)
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
for script in "${scripts[@]}"; do
|
|
||||||
source "$script"
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -x "$PYENV_COMMAND_PATH" ]; then
|
|
||||||
echo "$PYENV_COMMAND_PATH"
|
|
||||||
else
|
|
||||||
if (( ${#nonexistent_versions[@]} )); then
|
|
||||||
for version in "${nonexistent_versions[@]}"; do
|
|
||||||
echo "pyenv: version \`$version' is not installed (set by $(pyenv-version-origin))" >&2
|
|
||||||
done
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "pyenv: $PYENV_COMMAND: command not found" >&2
|
|
||||||
|
|
||||||
versions="$(pyenv-whence "$PYENV_COMMAND" || true)"
|
|
||||||
if [ -n "$versions" ]; then
|
|
||||||
{ echo
|
|
||||||
echo "The \`$1' command exists in these Python versions:"
|
|
||||||
echo "$versions" | sed 's/^/ /g'
|
|
||||||
echo
|
|
||||||
echo "Note: See 'pyenv help global' for tips on allowing both"
|
|
||||||
echo " python2 and python3 to be found."
|
|
||||||
} >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 127
|
|
||||||
fi
|
|
||||||
129
libexec/rbenv
Executable file
129
libexec/rbenv
Executable file
@@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$1" = "--debug" ]; then
|
||||||
|
export RBENV_DEBUG=1
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$RBENV_DEBUG" ]; then
|
||||||
|
# https://web.archive.org/web/20221105082147/https://wiki-dev.bash-hackers.org/scripting/debuggingtips#making_xtrace_more_useful
|
||||||
|
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
abort() {
|
||||||
|
{ if [ "$#" -eq 0 ]; then cat -
|
||||||
|
else echo "rbenv: $*"
|
||||||
|
fi
|
||||||
|
} >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -z "${RBENV_ROOT}" ]; then
|
||||||
|
RBENV_ROOT="${HOME}/.rbenv"
|
||||||
|
else
|
||||||
|
RBENV_ROOT="${RBENV_ROOT%/}"
|
||||||
|
fi
|
||||||
|
export RBENV_ROOT
|
||||||
|
|
||||||
|
if [ -z "${RBENV_DIR}" ]; then
|
||||||
|
RBENV_DIR="$PWD"
|
||||||
|
else
|
||||||
|
[[ $RBENV_DIR == /* ]] || RBENV_DIR="$PWD/$RBENV_DIR"
|
||||||
|
cd "$RBENV_DIR" 2>/dev/null || abort "cannot change working directory to \`$RBENV_DIR'"
|
||||||
|
RBENV_DIR="$PWD"
|
||||||
|
cd "$OLDPWD"
|
||||||
|
fi
|
||||||
|
export RBENV_DIR
|
||||||
|
|
||||||
|
[ -n "$RBENV_ORIG_PATH" ] || export RBENV_ORIG_PATH="$PATH"
|
||||||
|
|
||||||
|
canonicalize() {
|
||||||
|
local readlink resolved_path
|
||||||
|
if readlink="$(type -P greadlink)" || readlink="$(type -P readlink)"; then
|
||||||
|
# happy path: GNU & BSD readlink, macOS 12.3+
|
||||||
|
if resolved_path="$("$readlink" -f "$1" 2>/dev/null)"; then
|
||||||
|
printf "%s\n" "$resolved_path"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
# likely macOS < 12.3 with old readlink
|
||||||
|
local path="$1"
|
||||||
|
while [ -L "$path" ]; do
|
||||||
|
resolved_path="$("$readlink" "$path" 2>/dev/null)"
|
||||||
|
[[ $resolved_path == /* ]] || resolved_path="$(cd "${path%/*}/${resolved_path%/*}" && pwd)/${resolved_path##*/}"
|
||||||
|
path="$resolved_path"
|
||||||
|
done
|
||||||
|
printf "%s\n" "$path"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
# fail if the argument is a symlink and was not canonicalized
|
||||||
|
[ ! -L "$1" ] || return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
# all this trouble just to find out where rbenv's executables live
|
||||||
|
rbenv_bin="${BASH_SOURCE:-$0}"
|
||||||
|
if libexec_dir="$(canonicalize "$rbenv_bin")"; then
|
||||||
|
libexec_dir="${libexec_dir%/*}"
|
||||||
|
else
|
||||||
|
libexec_dir="${rbenv_bin%/*}"
|
||||||
|
[ "$libexec_dir" != "." ] || libexec_dir="$PWD"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for plugin_bin in "${RBENV_ROOT}/plugins/"*/bin; do
|
||||||
|
PATH="${plugin_bin}:${PATH}"
|
||||||
|
done
|
||||||
|
export PATH="${libexec_dir}:${PATH}"
|
||||||
|
|
||||||
|
RBENV_HOOK_PATH="${RBENV_HOOK_PATH}:${RBENV_ROOT}/rbenv.d"
|
||||||
|
if [ ! "${libexec_dir%/*}"/rbenv.d -ef "$RBENV_ROOT"/rbenv.d ]; then
|
||||||
|
# Add rbenv's own `rbenv.d` unless rbenv was cloned to RBENV_ROOT
|
||||||
|
RBENV_HOOK_PATH="${RBENV_HOOK_PATH}:${libexec_dir%/*}/rbenv.d"
|
||||||
|
fi
|
||||||
|
RBENV_HOOK_PATH="${RBENV_HOOK_PATH}:/usr/etc/rbenv.d:/usr/local/etc/rbenv.d:/etc/rbenv.d:/usr/lib/rbenv/hooks"
|
||||||
|
for plugin_hook in "${RBENV_ROOT}/plugins/"*/etc/rbenv.d; do
|
||||||
|
RBENV_HOOK_PATH="${RBENV_HOOK_PATH}:${plugin_hook}"
|
||||||
|
done
|
||||||
|
RBENV_HOOK_PATH="${RBENV_HOOK_PATH#:}"
|
||||||
|
export RBENV_HOOK_PATH
|
||||||
|
|
||||||
|
shopt -u nullglob
|
||||||
|
|
||||||
|
|
||||||
|
command="$1"
|
||||||
|
case "$command" in
|
||||||
|
"" )
|
||||||
|
{ rbenv---version
|
||||||
|
rbenv-help
|
||||||
|
} | abort
|
||||||
|
;;
|
||||||
|
-v | --version )
|
||||||
|
exec rbenv---version
|
||||||
|
;;
|
||||||
|
-h | --help )
|
||||||
|
exec rbenv-help
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
command_path="$(type -P "rbenv-$command" || true)"
|
||||||
|
if [ -z "$command_path" ]; then
|
||||||
|
if [ "$command" == "shell" ]; then
|
||||||
|
abort "shell integration not enabled. Run \`rbenv init' for instructions."
|
||||||
|
else
|
||||||
|
abort "no such command \`$command'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
shift 1
|
||||||
|
if [ "$1" = --help ]; then
|
||||||
|
if [[ "$command" == "sh-"* ]]; then
|
||||||
|
echo "rbenv help \"$command\""
|
||||||
|
else
|
||||||
|
exec rbenv-help "$command"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exec "$command_path" "$@"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Summary: Display the version of pyenv
|
# Summary: Display the version of rbenv
|
||||||
#
|
#
|
||||||
# Displays the version number of this pyenv release, including the
|
# Displays the version number of this rbenv release, including the
|
||||||
# current revision from git, if available.
|
# current revision from git, if available.
|
||||||
#
|
#
|
||||||
# The format of the git revision is:
|
# The format of the git revision is:
|
||||||
@@ -10,14 +10,14 @@
|
|||||||
# tagged.
|
# tagged.
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
version="2.4.2"
|
version="1.3.2"
|
||||||
git_revision=""
|
git_revision=""
|
||||||
|
|
||||||
if cd "${BASH_SOURCE%/*}" 2>/dev/null && git remote -v 2>/dev/null | grep -q pyenv; then
|
if cd "${BASH_SOURCE%/*}" 2>/dev/null && git remote -v 2>/dev/null | grep -q rbenv; then
|
||||||
git_revision="$(git describe --tags HEAD 2>/dev/null || true)"
|
git_revision="$(git describe --tags HEAD 2>/dev/null || true)"
|
||||||
git_revision="${git_revision#v}"
|
git_revision="${git_revision#v}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "pyenv ${git_revision:-$version}"
|
echo "rbenv ${git_revision:-$version}"
|
||||||
50
libexec/rbenv-commands
Executable file
50
libexec/rbenv-commands
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Summary: List all available rbenv commands
|
||||||
|
# Usage: rbenv commands [--sh|--no-sh]
|
||||||
|
#
|
||||||
|
# List names of all rbenv commands, including 3rd-party ones found in the
|
||||||
|
# PATH or in rbenv plugins. With `--sh`, list only shell commands.
|
||||||
|
#
|
||||||
|
# This functionality is mainly meant for scripting. To see usage help for
|
||||||
|
# rbenv, run `rbenv help`.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$1" = "--complete" ]; then
|
||||||
|
echo --sh
|
||||||
|
echo --no-sh
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
exclude_shell=
|
||||||
|
command_prefix="rbenv-"
|
||||||
|
|
||||||
|
if [ "$1" = "--sh" ]; then
|
||||||
|
command_prefix="rbenv-sh-"
|
||||||
|
shift
|
||||||
|
elif [ "$1" = "--no-sh" ]; then
|
||||||
|
exclude_shell=1
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
{
|
||||||
|
PATH_remain="$PATH"
|
||||||
|
# traverse PATH to find "rbenv-" prefixed commands
|
||||||
|
while true; do
|
||||||
|
path="${PATH_remain%%:*}"
|
||||||
|
if [ -n "$path" ]; then
|
||||||
|
for rbenv_command in "${path}/${command_prefix}"*; do
|
||||||
|
rbenv_command="${rbenv_command##*rbenv-}"
|
||||||
|
if [[ -z $exclude_shell || $rbenv_command != sh-* ]]; then
|
||||||
|
echo "${rbenv_command##sh-}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
[[ $PATH_remain == *:* ]] || break
|
||||||
|
PATH_remain="${PATH_remain#*:}"
|
||||||
|
done
|
||||||
|
} | sort | uniq
|
||||||
26
libexec/rbenv-completions
Executable file
26
libexec/rbenv-completions
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Usage: rbenv completions <command> [<args>...]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
COMMAND="$1"
|
||||||
|
if [ -z "$COMMAND" ]; then
|
||||||
|
rbenv-help --usage completions >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$COMMAND" = "--complete" ]; then
|
||||||
|
exec rbenv-commands
|
||||||
|
fi
|
||||||
|
|
||||||
|
COMMAND_PATH="$(type -P "rbenv-$COMMAND" "rbenv-sh-$COMMAND" | head -n1)"
|
||||||
|
|
||||||
|
# --help is provided automatically
|
||||||
|
echo --help
|
||||||
|
|
||||||
|
if grep -iE "^([#%]|--|//) provide rbenv completions" "$COMMAND_PATH" >/dev/null; then
|
||||||
|
shift
|
||||||
|
exec "$COMMAND_PATH" --complete "$@"
|
||||||
|
fi
|
||||||
46
libexec/rbenv-exec
Executable file
46
libexec/rbenv-exec
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Summary: Run an executable with the selected Ruby version
|
||||||
|
#
|
||||||
|
# Usage: rbenv exec <command> [<args>...]
|
||||||
|
#
|
||||||
|
# Runs an executable by first preparing PATH so that the selected Ruby
|
||||||
|
# version's `bin' directory is at the front.
|
||||||
|
#
|
||||||
|
# For example, if the currently selected Ruby version is 1.9.3-p327:
|
||||||
|
# rbenv exec bundle install
|
||||||
|
#
|
||||||
|
# is equivalent to:
|
||||||
|
# PATH="$RBENV_ROOT/versions/1.9.3-p327/bin:$PATH" bundle install
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$1" = "--complete" ]; then
|
||||||
|
exec rbenv-shims --short
|
||||||
|
fi
|
||||||
|
|
||||||
|
RBENV_VERSION="$(rbenv-version-name)"
|
||||||
|
RBENV_COMMAND="$1"
|
||||||
|
|
||||||
|
if [ -z "$RBENV_COMMAND" ]; then
|
||||||
|
rbenv-help --usage exec >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export RBENV_VERSION
|
||||||
|
RBENV_COMMAND_PATH="$(rbenv-which "$RBENV_COMMAND")"
|
||||||
|
RBENV_BIN_PATH="${RBENV_COMMAND_PATH%/*}"
|
||||||
|
|
||||||
|
IFS=$'\n' read -d '' -r -a scripts <<<"$(rbenv-hooks exec)" || true
|
||||||
|
for script in "${scripts[@]}"; do
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$script"
|
||||||
|
done
|
||||||
|
|
||||||
|
shift 1
|
||||||
|
if [ "$RBENV_VERSION" != "system" ]; then
|
||||||
|
export PATH="${RBENV_BIN_PATH}:${PATH}"
|
||||||
|
fi
|
||||||
|
exec -a "$RBENV_COMMAND" "$RBENV_COMMAND_PATH" "$@"
|
||||||
31
libexec/rbenv-global
Executable file
31
libexec/rbenv-global
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Summary: Set or show the global Ruby version
|
||||||
|
#
|
||||||
|
# Usage: rbenv global <version>
|
||||||
|
#
|
||||||
|
# Sets the global Ruby version. You can override the global version at
|
||||||
|
# any time by setting a directory-specific version with `rbenv local'
|
||||||
|
# or by setting the `RBENV_VERSION' environment variable.
|
||||||
|
#
|
||||||
|
# <version> should be a string matching a Ruby version known to rbenv.
|
||||||
|
# The special version string `system' will use your default system Ruby.
|
||||||
|
# Run `rbenv versions' for a list of available Ruby versions.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$1" = "--complete" ]; then
|
||||||
|
echo system
|
||||||
|
exec rbenv-versions --bare
|
||||||
|
fi
|
||||||
|
|
||||||
|
RBENV_VERSION="$1"
|
||||||
|
RBENV_VERSION_FILE="${RBENV_ROOT}/version"
|
||||||
|
|
||||||
|
if [ -n "$RBENV_VERSION" ]; then
|
||||||
|
rbenv-version-file-write "$RBENV_VERSION_FILE" "$RBENV_VERSION"
|
||||||
|
else
|
||||||
|
rbenv-version-file-read "$RBENV_VERSION_FILE" || echo system
|
||||||
|
fi
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#
|
#
|
||||||
# Summary: Display help for a command
|
# Summary: Display help for a command
|
||||||
#
|
#
|
||||||
# Usage: pyenv help [--usage] COMMAND
|
# Usage: rbenv help [--usage] COMMAND
|
||||||
#
|
#
|
||||||
# Parses and displays help contents from a command's source file.
|
# Parses and displays help contents from a command's source file.
|
||||||
#
|
#
|
||||||
@@ -13,22 +13,20 @@
|
|||||||
# documentation.
|
# documentation.
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
# Provide pyenv completions
|
# Provide rbenv completions
|
||||||
if [ "$1" = "--complete" ]; then
|
if [ "$1" = "--complete" ]; then
|
||||||
echo --usage
|
echo --usage
|
||||||
exec pyenv-commands
|
exec rbenv-commands
|
||||||
fi
|
fi
|
||||||
|
|
||||||
command_path() {
|
command_path() {
|
||||||
local command="$1"
|
local command="$1"
|
||||||
command -v pyenv-"$command" || command -v pyenv-sh-"$command" || true
|
type -P rbenv-"$command" rbenv-sh-"$command" | head -n1
|
||||||
}
|
}
|
||||||
|
|
||||||
extract_initial_comment_block() {
|
extract_initial_comment_block() {
|
||||||
LC_ALL= \
|
|
||||||
LC_CTYPE=C \
|
|
||||||
sed -ne "
|
sed -ne "
|
||||||
/^#/ !{
|
/^#/ !{
|
||||||
q
|
q
|
||||||
@@ -44,9 +42,15 @@ extract_initial_comment_block() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
collect_documentation() {
|
collect_documentation() {
|
||||||
# `tail` prevents "broken pipe" errors due to `head` closing the pipe without reading everything
|
local awk
|
||||||
# https://superuser.com/questions/554855/how-can-i-fix-a-broken-pipe-error/642932#642932
|
awk="$(type -P gawk)" || awk="$(type -P awk)" || true
|
||||||
$(type -P gawk awk | tail -n +1 | head -n1) '
|
if [ -z "$awk" ]; then
|
||||||
|
echo "rbenv: cannot find awk" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
"$awk" '
|
||||||
/^Summary:/ {
|
/^Summary:/ {
|
||||||
summary = substr($0, 10)
|
summary = substr($0, 10)
|
||||||
next
|
next
|
||||||
@@ -123,7 +127,7 @@ print_help() {
|
|||||||
if [ -n "$usage" ]; then
|
if [ -n "$usage" ]; then
|
||||||
echo "$usage"
|
echo "$usage"
|
||||||
else
|
else
|
||||||
echo "Usage: pyenv ${command}"
|
echo "Usage: rbenv ${command}"
|
||||||
fi
|
fi
|
||||||
if [ -n "$help" ]; then
|
if [ -n "$help" ]; then
|
||||||
echo
|
echo
|
||||||
@@ -140,24 +144,62 @@ print_usage() {
|
|||||||
local command="$1"
|
local command="$1"
|
||||||
local summary usage help
|
local summary usage help
|
||||||
eval "$(documentation_for "$command")"
|
eval "$(documentation_for "$command")"
|
||||||
[ -z "$usage" ] || echo "$usage"
|
if [ -n "$usage" ]; then
|
||||||
|
echo "$usage"
|
||||||
|
else
|
||||||
|
echo "Usage: rbenv ${command}"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if [ "$1" = "--complete-commands" ]; then
|
||||||
|
command_prefix="${2:-}"
|
||||||
|
seen=()
|
||||||
|
shopt -s nullglob
|
||||||
|
PATH_remain="$PATH"
|
||||||
|
# traverse PATH to find "rbenv-" prefixed commands
|
||||||
|
while true; do
|
||||||
|
path="${PATH_remain%%:*}"
|
||||||
|
if [ -n "$path" ]; then
|
||||||
|
for rbenv_command in "${path}/rbenv-"*; do
|
||||||
|
command_name="${rbenv_command##*/}"
|
||||||
|
command_name="${command_name#rbenv-}"
|
||||||
|
command_name="${command_name#sh-}"
|
||||||
|
[[ $command_name == "${command_prefix}"* ]] || continue
|
||||||
|
[[ " ${seen[*]} " != *" ${command_name} "* ]] || continue
|
||||||
|
seen+=("$command_name")
|
||||||
|
summary=""
|
||||||
|
eval "$(extract_initial_comment_block < "$rbenv_command" | collect_documentation)"
|
||||||
|
[ -n "$summary" ] || continue
|
||||||
|
printf "%s:%s\n" "$command_name" "$summary"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
[[ $PATH_remain == *:* ]] || break
|
||||||
|
PATH_remain="${PATH_remain#*:}"
|
||||||
|
done
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
unset usage
|
unset usage
|
||||||
if [ "$1" = "--usage" ]; then
|
if [ "$1" = "--usage" ]; then
|
||||||
usage="1"
|
usage="1"
|
||||||
shift
|
shift
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$1" ] || [ "$1" == "pyenv" ]; then
|
if [ -z "$1" ] || [ "$1" == "rbenv" ]; then
|
||||||
echo "Usage: pyenv <command> [<args>]"
|
if [ -z "$usage" ] && [ -t 1 ] && type -P man >/dev/null; then
|
||||||
[ -z "$usage" ] || exit
|
MANPATH="${BASH_SOURCE%/*}/../share/man:$MANPATH" exec man rbenv
|
||||||
|
fi
|
||||||
|
echo "Usage: rbenv <command> [<args>...]"
|
||||||
|
[ -n "$usage" ] && exit
|
||||||
echo
|
echo
|
||||||
echo "Some useful pyenv commands are:"
|
echo "Commands to manage available Ruby versions:"
|
||||||
print_summaries $(exec pyenv-commands | sort -u)
|
print_summaries versions install uninstall rehash
|
||||||
echo
|
echo
|
||||||
echo "See \`pyenv help <command>' for information on a specific command."
|
echo "Commands to view or change the current Ruby version:"
|
||||||
echo "For full documentation, see: https://github.com/pyenv/pyenv#readme"
|
print_summaries version local global shell
|
||||||
|
echo
|
||||||
|
echo "See \`rbenv help <command>' for information on a specific command."
|
||||||
|
echo "For full documentation, see: https://github.com/rbenv/rbenv#readme"
|
||||||
else
|
else
|
||||||
command="$1"
|
command="$1"
|
||||||
if [ -n "$(command_path "$command")" ]; then
|
if [ -n "$(command_path "$command")" ]; then
|
||||||
@@ -167,7 +209,7 @@ else
|
|||||||
print_help "$command"
|
print_help "$command"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "pyenv: no such command \`$command'" >&2
|
echo "rbenv: no such command \`$command'" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
32
libexec/rbenv-hooks
Executable file
32
libexec/rbenv-hooks
Executable file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Summary: List hook scripts for a given rbenv command
|
||||||
|
# Usage: rbenv hooks <command>
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$1" = "--complete" ]; then
|
||||||
|
echo exec
|
||||||
|
echo rehash
|
||||||
|
echo version-name
|
||||||
|
echo version-origin
|
||||||
|
echo which
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
RBENV_COMMAND="$1"
|
||||||
|
if [ -z "$RBENV_COMMAND" ]; then
|
||||||
|
rbenv-help --usage hooks >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=: read -r -a hook_paths <<<"$RBENV_HOOK_PATH"
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
for path in "${hook_paths[@]}"; do
|
||||||
|
for script in "$path/$RBENV_COMMAND"/*.bash; do
|
||||||
|
echo "$script"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
shopt -u nullglob
|
||||||
222
libexec/rbenv-init
Executable file
222
libexec/rbenv-init
Executable file
@@ -0,0 +1,222 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Summary: Configure the shell environment for rbenv
|
||||||
|
# Usage: rbenv init [<shells>...]
|
||||||
|
# rbenv init - [--no-rehash] [<shell>]
|
||||||
|
#
|
||||||
|
# Modifies shell initialization files to bootstrap rbenv functionality.
|
||||||
|
# Typically, this will add a line that eval's the output of `rbenv init -`.
|
||||||
|
# If no shells are named by arguments, the current shell will be detected
|
||||||
|
# by inspecting the parent process. If a shell is already configured for
|
||||||
|
# rbenv, the init command does nothing and exits with zero status.
|
||||||
|
#
|
||||||
|
# In the `rbenv init -` mode, this outputs a script to be eval'd in the
|
||||||
|
# current shell. Most importantly, that script prepends the rbenv shims
|
||||||
|
# directory to the PATH environment variable. To aid interactive shells,
|
||||||
|
# the script also installs the magic `rbenv()` shell function and loads
|
||||||
|
# shell completions for rbenv commands.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$1" = "--complete" ]; then
|
||||||
|
echo -
|
||||||
|
echo --no-rehash
|
||||||
|
echo bash
|
||||||
|
echo fish
|
||||||
|
echo ksh
|
||||||
|
echo zsh
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
print=""
|
||||||
|
no_rehash=""
|
||||||
|
shells=()
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
"-" )
|
||||||
|
print=1
|
||||||
|
;;
|
||||||
|
"--no-rehash" )
|
||||||
|
no_rehash=1
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
shells+=("$1")
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "${#shells[@]}" -eq 0 ]; then
|
||||||
|
shell="$(ps -p "$PPID" -o 'args=' 2>/dev/null || true)"
|
||||||
|
shell="${shell%% *}"
|
||||||
|
shell="${shell##-}"
|
||||||
|
shell="${shell:-$SHELL}"
|
||||||
|
shell="${shell##*/}"
|
||||||
|
shells=("${shell%%-*}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
root="${BASH_SOURCE:-$0}"
|
||||||
|
root="${root%/*}"
|
||||||
|
root="${root%/*}"
|
||||||
|
|
||||||
|
rbenv_in_path=true
|
||||||
|
if [ -n "$RBENV_ORIG_PATH" ]; then
|
||||||
|
PATH="$RBENV_ORIG_PATH" type -P rbenv >/dev/null || rbenv_in_path=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$print" ]; then
|
||||||
|
display_path() {
|
||||||
|
if [ "${1/#$HOME\/}" != "$1" ]; then
|
||||||
|
# shellcheck disable=SC2088
|
||||||
|
printf '~/%s' "${1/#$HOME\/}"
|
||||||
|
else
|
||||||
|
printf '%s' "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
rbenv_command=rbenv
|
||||||
|
if [ -z "$rbenv_in_path" ]; then
|
||||||
|
rbenv_command="$(display_path "$root/bin/rbenv")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
color_start=""
|
||||||
|
color_end=""
|
||||||
|
if [ -t 1 ]; then
|
||||||
|
color_start=$'\e[33;1m'
|
||||||
|
color_end=$'\e[m'
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_config() {
|
||||||
|
if grep -q "rbenv init" "$1" 2>/dev/null; then
|
||||||
|
printf 'skipping %s%s%s: already configured for rbenv.\n' "$color_start" "$(display_path "$1")" "$color_end"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
mkdir -p "${1%/*}"
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
printf '\n# Added by `rbenv init` on %s\n%s\n' "$(date)" "$2" >> "$1"
|
||||||
|
printf 'writing %s%s%s: now configured for rbenv.\n' "$color_start" "$(display_path "$1")" "$color_end"
|
||||||
|
}
|
||||||
|
|
||||||
|
status=0
|
||||||
|
for shell in "${shells[@]}"; do
|
||||||
|
case "$shell" in
|
||||||
|
bash )
|
||||||
|
if [ -f ~/.bashrc ] && [ ! -f ~/.bash_profile ]; then
|
||||||
|
profile="$HOME/.bashrc"
|
||||||
|
else
|
||||||
|
# shellcheck disable=SC2012
|
||||||
|
profile="$(ls ~/.bash_profile ~/.bash_login ~/.profile 2>/dev/null | head -n1)"
|
||||||
|
[ -n "$profile" ] || profile="$HOME/.bash_profile"
|
||||||
|
fi
|
||||||
|
write_config "$profile" \
|
||||||
|
"eval \"\$($rbenv_command init - --no-rehash bash)\""
|
||||||
|
;;
|
||||||
|
zsh )
|
||||||
|
# check zshrc for backward compatibility with older rbenv init
|
||||||
|
if grep -q rbenv "${ZDOTDIR:-$HOME}/.zshrc" 2>/dev/null; then
|
||||||
|
profile="${ZDOTDIR:-$HOME}/.zshrc"
|
||||||
|
else
|
||||||
|
profile="${ZDOTDIR:-$HOME}/.zprofile"
|
||||||
|
fi
|
||||||
|
write_config "$profile" \
|
||||||
|
"eval \"\$($rbenv_command init - --no-rehash zsh)\""
|
||||||
|
;;
|
||||||
|
ksh | ksh93 | mksh )
|
||||||
|
# There are two implementations of Korn shell: AT&T (ksh93) and Mir (mksh).
|
||||||
|
# Systems may have them installed under those names, or as ksh, so those
|
||||||
|
# are recognized here. The obsolete ksh88 (subsumed by ksh93) and pdksh
|
||||||
|
# (subsumed by mksh) are not included, since they are unlikely to still
|
||||||
|
# be in use as interactive shells anywhere.
|
||||||
|
write_config "$HOME/.profile" \
|
||||||
|
"eval \"\$($rbenv_command init - ksh)\""
|
||||||
|
;;
|
||||||
|
fish )
|
||||||
|
write_config "${XDG_CONFIG_HOME:-$HOME/.config}/fish/config.fish" \
|
||||||
|
"status --is-interactive; and $rbenv_command init - --no-rehash fish | source"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
printf 'unsupported shell: "%s"\n' "$shell" >&2
|
||||||
|
status=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
exit $status
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${RBENV_ROOT}/"{shims,versions}
|
||||||
|
|
||||||
|
shell="${shells[0]}"
|
||||||
|
case "$shell" in
|
||||||
|
fish )
|
||||||
|
[ -n "$rbenv_in_path" ] || printf "set -gx PATH '%s/bin' \$PATH\n" "$root"
|
||||||
|
printf "set -gx PATH '%s/shims' \$PATH\n" "$RBENV_ROOT"
|
||||||
|
printf 'set -gx RBENV_SHELL %s\n' "$shell"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
[ -n "$rbenv_in_path" ] || printf 'export PATH="%s/bin:${PATH}"\n' "$root"
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
printf 'export PATH="%s/shims:${PATH}"\n' "$RBENV_ROOT"
|
||||||
|
printf 'export RBENV_SHELL=%s\n' "$shell"
|
||||||
|
|
||||||
|
completion="${root}/completions/rbenv.${shell}"
|
||||||
|
if [ -r "$completion" ]; then
|
||||||
|
printf "source '%s'\n" "$completion"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -z "$no_rehash" ]; then
|
||||||
|
echo 'command rbenv rehash 2>/dev/null'
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=$'\n' read -d '' -r -a commands <<<"$(rbenv-commands --sh)" || true
|
||||||
|
|
||||||
|
case "$shell" in
|
||||||
|
fish )
|
||||||
|
cat <<EOS
|
||||||
|
function rbenv
|
||||||
|
set command \$argv[1]
|
||||||
|
set -e argv[1]
|
||||||
|
|
||||||
|
switch "\$command"
|
||||||
|
case ${commands[*]}
|
||||||
|
rbenv "sh-\$command" \$argv|source
|
||||||
|
case '*'
|
||||||
|
command rbenv "\$command" \$argv
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
;;
|
||||||
|
ksh | ksh93 | mksh )
|
||||||
|
cat <<EOS
|
||||||
|
function rbenv {
|
||||||
|
typeset command
|
||||||
|
EOS
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
cat <<EOS
|
||||||
|
rbenv() {
|
||||||
|
local command
|
||||||
|
EOS
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$shell" != "fish" ]; then
|
||||||
|
IFS="|"
|
||||||
|
cat <<EOS
|
||||||
|
command="\${1:-}"
|
||||||
|
if [ "\$#" -gt 0 ]; then
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "\$command" in
|
||||||
|
${commands[*]})
|
||||||
|
eval "\$(rbenv "sh-\$command" "\$@")";;
|
||||||
|
*)
|
||||||
|
command rbenv "\$command" "\$@";;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
EOS
|
||||||
|
fi
|
||||||
45
libexec/rbenv-local
Executable file
45
libexec/rbenv-local
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Summary: Set or show the local application-specific Ruby version
|
||||||
|
#
|
||||||
|
# Usage: rbenv local <version>
|
||||||
|
# rbenv local --unset
|
||||||
|
#
|
||||||
|
# Sets the local application-specific Ruby version by writing the
|
||||||
|
# version name to a file named `.ruby-version'.
|
||||||
|
#
|
||||||
|
# When you run a Ruby command, rbenv will look for a `.ruby-version'
|
||||||
|
# file in the current directory and each parent directory. If no such
|
||||||
|
# file is found in the tree, rbenv will use the global Ruby version
|
||||||
|
# specified with `rbenv global'. A version specified with the
|
||||||
|
# `RBENV_VERSION' environment variable takes precedence over local
|
||||||
|
# and global versions.
|
||||||
|
#
|
||||||
|
# <version> should be a string matching a Ruby version known to rbenv.
|
||||||
|
# The special version string `system' will use your default system Ruby.
|
||||||
|
# Run `rbenv versions' for a list of available Ruby versions.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$1" = "--complete" ]; then
|
||||||
|
echo --unset
|
||||||
|
echo system
|
||||||
|
exec rbenv-versions --bare
|
||||||
|
fi
|
||||||
|
|
||||||
|
RBENV_VERSION="$1"
|
||||||
|
|
||||||
|
if [ "$RBENV_VERSION" = "--unset" ]; then
|
||||||
|
rm -f .ruby-version
|
||||||
|
elif [ -n "$RBENV_VERSION" ]; then
|
||||||
|
rbenv-version-file-write .ruby-version "$RBENV_VERSION"
|
||||||
|
else
|
||||||
|
if version_file="$(rbenv-version-file "$PWD")"; then
|
||||||
|
rbenv-version-file-read "$version_file"
|
||||||
|
else
|
||||||
|
echo "rbenv: no local version configured for this directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
42
libexec/rbenv-prefix
Executable file
42
libexec/rbenv-prefix
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Summary: Display prefix for a Ruby version
|
||||||
|
# Usage: rbenv prefix [<version>]
|
||||||
|
#
|
||||||
|
# Displays the directory where a Ruby version is installed. If no
|
||||||
|
# version is given, `rbenv prefix' displays the location of the
|
||||||
|
# currently selected version.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$1" = "--complete" ]; then
|
||||||
|
echo system
|
||||||
|
exec rbenv-versions --bare
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
export RBENV_VERSION="$1"
|
||||||
|
elif [ -z "$RBENV_VERSION" ]; then
|
||||||
|
RBENV_VERSION="$(rbenv-version-name)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$RBENV_VERSION" = "system" ]; then
|
||||||
|
if RUBY_PATH="$(rbenv-which ruby)"; then
|
||||||
|
RUBY_PATH="${RUBY_PATH%/*}"
|
||||||
|
RBENV_PREFIX_PATH="${RUBY_PATH%/bin}"
|
||||||
|
echo "${RBENV_PREFIX_PATH:-/}"
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
echo "rbenv: system version not found in PATH" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
RBENV_PREFIX_PATH="${RBENV_ROOT}/versions/${RBENV_VERSION}"
|
||||||
|
if [ ! -d "$RBENV_PREFIX_PATH" ]; then
|
||||||
|
echo "rbenv: version \`${RBENV_VERSION}' not installed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$RBENV_PREFIX_PATH"
|
||||||
180
libexec/rbenv-rehash
Executable file
180
libexec/rbenv-rehash
Executable file
@@ -0,0 +1,180 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Summary: Regenerate rbenv shims
|
||||||
|
#
|
||||||
|
# Regenerate shims for every Ruby executable in `$RBENV_ROOT/versions/*/bin'
|
||||||
|
# and write them to the `$RBENV_ROOT/shims' directory. A shell environment
|
||||||
|
# properly set up for rbenv will have this shims directory in PATH, which is
|
||||||
|
# the core mechanism for Ruby version switching.
|
||||||
|
#
|
||||||
|
# Running rbenv rehash should only be necessary after installing new Ruby
|
||||||
|
# versions or gems. Note that this is sometimes done automatically: the
|
||||||
|
# `rbenv install' command from the ruby-build plugin runs rehash after
|
||||||
|
# every successful installation, and a RubyGems plugin that ships with
|
||||||
|
# rbenv runs rehash after every `gem install' command.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
SHIM_PATH="${RBENV_ROOT}/shims"
|
||||||
|
PROTOTYPE_SHIM_PATH="${SHIM_PATH}/.rbenv-shim"
|
||||||
|
|
||||||
|
# Create the shims directory if it doesn't already exist.
|
||||||
|
mkdir -p "$SHIM_PATH"
|
||||||
|
|
||||||
|
# Ensure only one instance of rbenv-rehash is running at a time by
|
||||||
|
# setting the shell's `noclobber` option and attempting to write to
|
||||||
|
# the prototype shim file. If the file already exists, print a warning
|
||||||
|
# to stderr and exit with a non-zero status.
|
||||||
|
set -o noclobber
|
||||||
|
{ echo > "$PROTOTYPE_SHIM_PATH"
|
||||||
|
} 2>| /dev/null ||
|
||||||
|
{ if [ -w "$SHIM_PATH" ]; then
|
||||||
|
echo "rbenv: cannot rehash: $PROTOTYPE_SHIM_PATH exists"
|
||||||
|
else
|
||||||
|
echo "rbenv: cannot rehash: $SHIM_PATH isn't writable"
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
set +o noclobber
|
||||||
|
|
||||||
|
# If we were able to obtain a lock, register a trap to clean up the
|
||||||
|
# prototype shim when the process exits.
|
||||||
|
trap remove_prototype_shim EXIT
|
||||||
|
|
||||||
|
remove_prototype_shim() {
|
||||||
|
rm -f "$PROTOTYPE_SHIM_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Locates rbenv as found in the user's PATH. Otherwise, returns an
|
||||||
|
# absolute path to the rbenv executable itself.
|
||||||
|
rbenv_path() {
|
||||||
|
local found
|
||||||
|
found="$(PATH="$RBENV_ORIG_PATH" type -P rbenv)"
|
||||||
|
if [[ $found == /* ]]; then
|
||||||
|
echo "$found"
|
||||||
|
elif [[ -n "$found" ]]; then
|
||||||
|
echo "$PWD/${found#./}"
|
||||||
|
else
|
||||||
|
# Assume rbenv isn't in PATH.
|
||||||
|
echo "${BASH_SOURCE%/*}/rbenv"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# The prototype shim file is a script that re-execs itself, passing
|
||||||
|
# its filename and any arguments to `rbenv exec`. This file is
|
||||||
|
# hard-linked for every executable and then removed. The linking
|
||||||
|
# technique is fast, uses less disk space than unique files, and also
|
||||||
|
# serves as a locking mechanism.
|
||||||
|
create_prototype_shim() {
|
||||||
|
cat > "$PROTOTYPE_SHIM_PATH" <<SH
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
[ -n "\$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
program="\${0##*/}"
|
||||||
|
if [ "\$program" = "ruby" ]; then
|
||||||
|
for arg; do
|
||||||
|
case "\$arg" in
|
||||||
|
-e* | -- ) break ;;
|
||||||
|
*/* )
|
||||||
|
if [ -f "\$arg" ]; then
|
||||||
|
export RBENV_DIR="\${arg%/*}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
export RBENV_ROOT="$RBENV_ROOT"
|
||||||
|
exec "$(rbenv_path)" exec "\$program" "\$@"
|
||||||
|
SH
|
||||||
|
chmod +x "$PROTOTYPE_SHIM_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
# If the contents of the prototype shim file differ from the contents
|
||||||
|
# of the first shim in the shims directory, assume rbenv has been
|
||||||
|
# upgraded and the existing shims need to be removed.
|
||||||
|
remove_outdated_shims() {
|
||||||
|
local shim
|
||||||
|
for shim in "$SHIM_PATH"/*; do
|
||||||
|
if ! diff "$PROTOTYPE_SHIM_PATH" "$shim" >/dev/null 2>&1; then
|
||||||
|
rm -f "$SHIM_PATH"/*
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# List basenames of executables for every Ruby version
|
||||||
|
list_executable_names() {
|
||||||
|
local version file
|
||||||
|
rbenv-versions --bare --skip-aliases | \
|
||||||
|
while read -r version; do
|
||||||
|
for file in "${RBENV_ROOT}/versions/${version}/bin/"*; do
|
||||||
|
echo "${file##*/}"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
if [ -n "$GEM_HOME" ]; then
|
||||||
|
for file in "$GEM_HOME"/bin/*; do
|
||||||
|
echo "${file##*/}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# The basename of each argument passed to `make_shims` will be
|
||||||
|
# registered for installation as a shim. In this way, plugins may call
|
||||||
|
# `make_shims` with a glob to register many shims at once.
|
||||||
|
make_shims() {
|
||||||
|
local file shim
|
||||||
|
for file; do
|
||||||
|
shim="${file##*/}"
|
||||||
|
registered_shims+=("$shim")
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Registers the name of a shim to be generated.
|
||||||
|
register_shim() {
|
||||||
|
registered_shims+=("$1")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install all the shims registered via `make_shims` or `register_shim` directly.
|
||||||
|
install_registered_shims() {
|
||||||
|
local shim file
|
||||||
|
for shim in "${registered_shims[@]}"; do
|
||||||
|
file="${SHIM_PATH}/${shim}"
|
||||||
|
[ -e "$file" ] || cp "$PROTOTYPE_SHIM_PATH" "$file"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Once the registered shims have been installed, we make a second pass
|
||||||
|
# over the contents of the shims directory. Any file that is present
|
||||||
|
# in the directory but has not been registered as a shim should be
|
||||||
|
# removed.
|
||||||
|
remove_stale_shims() {
|
||||||
|
local shim
|
||||||
|
local known_shims=" ${registered_shims[*]} "
|
||||||
|
for shim in "$SHIM_PATH"/*; do
|
||||||
|
if [[ "$known_shims" != *" ${shim##*/} "* ]]; then
|
||||||
|
rm -f "$shim"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
# Create the prototype shim, then register shims for all known
|
||||||
|
# executables.
|
||||||
|
create_prototype_shim
|
||||||
|
remove_outdated_shims
|
||||||
|
# shellcheck disable=SC2207
|
||||||
|
registered_shims=( $(list_executable_names | sort -u) )
|
||||||
|
|
||||||
|
# Allow plugins to register shims.
|
||||||
|
IFS=$'\n' read -d '' -r -a scripts <<<"$(rbenv-hooks rehash)" || true
|
||||||
|
for script in "${scripts[@]}"; do
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$script"
|
||||||
|
done
|
||||||
|
|
||||||
|
install_registered_shims
|
||||||
|
remove_stale_shims
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Summary: Display the root directory where versions and shims are kept
|
# Summary: Display the root directory where versions and shims are kept
|
||||||
echo "$PYENV_ROOT"
|
echo "$RBENV_ROOT"
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -e
|
set -e
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
# Provide pyenv completions
|
# Provide rbenv completions
|
||||||
if [ "$1" = "--complete" ]; then
|
if [ "$1" = "--complete" ]; then
|
||||||
exec pyenv-rehash --complete
|
exec rbenv-rehash --complete
|
||||||
fi
|
fi
|
||||||
|
|
||||||
shell="$(basename "${PYENV_SHELL:-$SHELL}")"
|
shell="$(basename "${RBENV_SHELL:-$SHELL}")"
|
||||||
|
|
||||||
# When pyenv shell integration is enabled, delegate to pyenv-rehash,
|
# When rbenv shell integration is enabled, delegate to rbenv-rehash,
|
||||||
# then tell the shell to empty its command lookup cache.
|
# then tell the shell to empty its command lookup cache.
|
||||||
pyenv-rehash
|
rbenv-rehash
|
||||||
|
|
||||||
case "$shell" in
|
case "$shell" in
|
||||||
fish )
|
fish )
|
||||||
144
libexec/rbenv-sh-shell
Executable file
144
libexec/rbenv-sh-shell
Executable file
@@ -0,0 +1,144 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Summary: Set or show the shell-specific Ruby version
|
||||||
|
#
|
||||||
|
# Usage: rbenv shell <version>
|
||||||
|
# rbenv shell -
|
||||||
|
# rbenv shell --unset
|
||||||
|
#
|
||||||
|
# Sets a shell-specific Ruby version by setting the `RBENV_VERSION'
|
||||||
|
# environment variable in your shell. This version overrides local
|
||||||
|
# application-specific versions and the global version.
|
||||||
|
#
|
||||||
|
# <version> should be a string matching a Ruby version known to rbenv.
|
||||||
|
# The special version string `system' will use your default system Ruby.
|
||||||
|
# Run `rbenv versions' for a list of available Ruby versions.
|
||||||
|
#
|
||||||
|
# When `-` is passed instead of the version string, the previously set
|
||||||
|
# version will be restored. With `--unset`, the `RBENV_VERSION`
|
||||||
|
# environment variable gets unset, restoring the environment to the
|
||||||
|
# state before the first `rbenv shell` call.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$1" = "--complete" ]; then
|
||||||
|
echo --unset
|
||||||
|
echo system
|
||||||
|
exec rbenv-versions --bare
|
||||||
|
fi
|
||||||
|
|
||||||
|
version="$1"
|
||||||
|
shell="$(basename "${RBENV_SHELL:-$SHELL}")"
|
||||||
|
|
||||||
|
if [ -z "$version" ]; then
|
||||||
|
if [ -z "$RBENV_VERSION" ]; then
|
||||||
|
echo "rbenv: no shell-specific version configured" >&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo 'echo "$RBENV_VERSION"'
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$version" = "--unset" ]; then
|
||||||
|
case "$shell" in
|
||||||
|
fish )
|
||||||
|
echo 'set -gu RBENV_VERSION_OLD "$RBENV_VERSION"'
|
||||||
|
echo "set -e RBENV_VERSION"
|
||||||
|
;;
|
||||||
|
zsh )
|
||||||
|
echo "typeset -g RBENV_VERSION_OLD=\"\${RBENV_VERSION-}\""
|
||||||
|
echo "unset RBENV_VERSION"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
echo 'RBENV_VERSION_OLD="${RBENV_VERSION-}"'
|
||||||
|
echo "unset RBENV_VERSION"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$version" = "-" ]; then
|
||||||
|
case "$shell" in
|
||||||
|
fish )
|
||||||
|
cat <<EOS
|
||||||
|
if set -q RBENV_VERSION_OLD
|
||||||
|
if [ -n "\$RBENV_VERSION_OLD" ]
|
||||||
|
set RBENV_VERSION_OLD_ "\$RBENV_VERSION"
|
||||||
|
set -gx RBENV_VERSION "\$RBENV_VERSION_OLD"
|
||||||
|
set -gu RBENV_VERSION_OLD "\$RBENV_VERSION_OLD_"
|
||||||
|
set -e RBENV_VERSION_OLD_
|
||||||
|
else
|
||||||
|
set -gu RBENV_VERSION_OLD "\$RBENV_VERSION"
|
||||||
|
set -e RBENV_VERSION
|
||||||
|
end
|
||||||
|
else
|
||||||
|
echo "rbenv: RBENV_VERSION_OLD is not set" >&2
|
||||||
|
false
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
;;
|
||||||
|
zsh )
|
||||||
|
cat <<EOS
|
||||||
|
if [ -n "\${RBENV_VERSION_OLD+x}" ]; then
|
||||||
|
if [ -n "\$RBENV_VERSION_OLD" ]; then
|
||||||
|
local RBENV_VERSION_OLD_="\$RBENV_VERSION"
|
||||||
|
export RBENV_VERSION="\$RBENV_VERSION_OLD"
|
||||||
|
RBENV_VERSION_OLD="\$RBENV_VERSION_OLD_"
|
||||||
|
unset RBENV_VERSION_OLD_
|
||||||
|
else
|
||||||
|
typeset -g RBENV_VERSION_OLD="\$RBENV_VERSION"
|
||||||
|
unset RBENV_VERSION
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "rbenv: RBENV_VERSION_OLD is not set" >&2
|
||||||
|
false
|
||||||
|
fi
|
||||||
|
EOS
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
cat <<EOS
|
||||||
|
if [ -n "\${RBENV_VERSION_OLD+x}" ]; then
|
||||||
|
if [ -n "\$RBENV_VERSION_OLD" ]; then
|
||||||
|
RBENV_VERSION_OLD_="\$RBENV_VERSION"
|
||||||
|
export RBENV_VERSION="\$RBENV_VERSION_OLD"
|
||||||
|
RBENV_VERSION_OLD="\$RBENV_VERSION_OLD_"
|
||||||
|
unset RBENV_VERSION_OLD_
|
||||||
|
else
|
||||||
|
RBENV_VERSION_OLD="\$RBENV_VERSION"
|
||||||
|
unset RBENV_VERSION
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "rbenv: RBENV_VERSION_OLD is not set" >&2
|
||||||
|
false
|
||||||
|
fi
|
||||||
|
EOS
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure the specified version is installed.
|
||||||
|
if rbenv-prefix "$version" >/dev/null; then
|
||||||
|
if [ "$version" != "$RBENV_VERSION" ]; then
|
||||||
|
case "$shell" in
|
||||||
|
fish )
|
||||||
|
echo 'set -gu RBENV_VERSION_OLD "$RBENV_VERSION"'
|
||||||
|
echo "set -gx RBENV_VERSION \"$version\""
|
||||||
|
;;
|
||||||
|
zsh )
|
||||||
|
echo "typeset -g RBENV_VERSION_OLD=\"\${RBENV_VERSION-}\""
|
||||||
|
echo "export RBENV_VERSION=\"$version\""
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
echo 'RBENV_VERSION_OLD="${RBENV_VERSION-}"'
|
||||||
|
echo "export RBENV_VERSION=\"$version\""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "false"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Summary: List existing pyenv shims
|
# Summary: List existing rbenv shims
|
||||||
# Usage: pyenv shims [--short]
|
# Usage: rbenv shims [--short]
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
# Provide pyenv completions
|
# Provide rbenv completions
|
||||||
if [ "$1" = "--complete" ]; then
|
if [ "$1" = "--complete" ]; then
|
||||||
echo --short
|
echo --short
|
||||||
exit
|
exit
|
||||||
@@ -13,7 +13,7 @@ fi
|
|||||||
|
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
|
|
||||||
for command in "${PYENV_ROOT}/shims/"*; do
|
for command in "${RBENV_ROOT}/shims/"*; do
|
||||||
if [ "$1" = "--short" ]; then
|
if [ "$1" = "--short" ]; then
|
||||||
echo "${command##*/}"
|
echo "${command##*/}"
|
||||||
else
|
else
|
||||||
18
libexec/rbenv-version
Executable file
18
libexec/rbenv-version
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Summary: Show the current Ruby version and its origin
|
||||||
|
#
|
||||||
|
# Shows the currently selected Ruby version and how it was
|
||||||
|
# selected. To obtain only the version string, use `rbenv
|
||||||
|
# version-name'.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
version_name="$(rbenv-version-name)"
|
||||||
|
version_origin="$(rbenv-version-origin)"
|
||||||
|
|
||||||
|
if [ "$version_origin" = "${RBENV_ROOT}/version" ] && [ ! -e "$version_origin" ]; then
|
||||||
|
echo "$version_name"
|
||||||
|
else
|
||||||
|
echo "$version_name (set by $version_origin)"
|
||||||
|
fi
|
||||||
34
libexec/rbenv-version-file
Executable file
34
libexec/rbenv-version-file
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Usage: rbenv version-file [<dir>]
|
||||||
|
# Summary: Detect the file that sets the current rbenv version
|
||||||
|
#
|
||||||
|
# Detects and prints the location of a `.ruby-version` file that sets the
|
||||||
|
# version for the current working directory. If no file found, this prints
|
||||||
|
# the location of the global version file, even if that file does
|
||||||
|
# not exist.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
target_dir="$1"
|
||||||
|
|
||||||
|
find_local_version_file() {
|
||||||
|
local root="$1"
|
||||||
|
while ! [[ "$root" =~ ^//[^/]*$ ]]; do
|
||||||
|
if [ -s "${root}/.ruby-version" ]; then
|
||||||
|
echo "${root}/.ruby-version"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
[ -n "$root" ] || break
|
||||||
|
root="${root%/*}"
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -n "$target_dir" ]; then
|
||||||
|
find_local_version_file "$target_dir"
|
||||||
|
else
|
||||||
|
find_local_version_file "$RBENV_DIR" || {
|
||||||
|
[ "$RBENV_DIR" != "$PWD" ] && find_local_version_file "$PWD"
|
||||||
|
} || echo "${RBENV_ROOT}/version"
|
||||||
|
fi
|
||||||
21
libexec/rbenv-version-file-read
Executable file
21
libexec/rbenv-version-file-read
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Usage: rbenv version-file-read <file>
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
VERSION_FILE="$1"
|
||||||
|
|
||||||
|
if [ -s "$VERSION_FILE" ]; then
|
||||||
|
# Read the first word from the specified version file. Avoid reading it whole.
|
||||||
|
IFS="${IFS}"$'\r'
|
||||||
|
read -n 1024 -d "" -r version _ <"$VERSION_FILE" || :
|
||||||
|
|
||||||
|
if [ "$version" = ".." ] || [[ $version == */* ]]; then
|
||||||
|
echo "rbenv: invalid version in \`$VERSION_FILE'" >&2
|
||||||
|
elif [ -n "$version" ]; then
|
||||||
|
echo "$version"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 1
|
||||||
19
libexec/rbenv-version-file-write
Executable file
19
libexec/rbenv-version-file-write
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Usage: rbenv version-file-write <file> <version>
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
RBENV_VERSION_FILE="$1"
|
||||||
|
RBENV_VERSION="$2"
|
||||||
|
|
||||||
|
if [ -z "$RBENV_VERSION" ] || [ -z "$RBENV_VERSION_FILE" ]; then
|
||||||
|
rbenv-help --usage version-file-write >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure the specified version is installed.
|
||||||
|
rbenv-prefix "$RBENV_VERSION" >/dev/null
|
||||||
|
|
||||||
|
# Write the version out to disk.
|
||||||
|
echo "$RBENV_VERSION" > "$RBENV_VERSION_FILE"
|
||||||
34
libexec/rbenv-version-name
Executable file
34
libexec/rbenv-version-name
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Summary: Show the current Ruby version
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
if [ -z "$RBENV_VERSION" ]; then
|
||||||
|
RBENV_VERSION_FILE="$(rbenv-version-file)"
|
||||||
|
RBENV_VERSION="$(rbenv-version-file-read "$RBENV_VERSION_FILE" || true)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=$'\n' read -d '' -r -a scripts <<<"$(rbenv-hooks version-name)" || true
|
||||||
|
for script in "${scripts[@]}"; do
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$script"
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$RBENV_VERSION" ] || [ "$RBENV_VERSION" = "system" ]; then
|
||||||
|
echo "system"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
version_exists() {
|
||||||
|
local version="$1"
|
||||||
|
[ -d "${RBENV_ROOT}/versions/${version}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
if version_exists "$RBENV_VERSION"; then
|
||||||
|
echo "$RBENV_VERSION"
|
||||||
|
elif version_exists "${RBENV_VERSION#ruby-}"; then
|
||||||
|
echo "${RBENV_VERSION#ruby-}"
|
||||||
|
else
|
||||||
|
echo "rbenv: version \`$RBENV_VERSION' is not installed (set by $(rbenv-version-origin))" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
20
libexec/rbenv-version-origin
Executable file
20
libexec/rbenv-version-origin
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Summary: Explain how the current Ruby version is set
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
unset RBENV_VERSION_ORIGIN
|
||||||
|
|
||||||
|
IFS=$'\n' read -d '' -r -a scripts <<<"$(rbenv-hooks version-origin)" || true
|
||||||
|
for script in "${scripts[@]}"; do
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$script"
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$RBENV_VERSION_ORIGIN" ]; then
|
||||||
|
echo "$RBENV_VERSION_ORIGIN"
|
||||||
|
elif [ -n "$RBENV_VERSION" ]; then
|
||||||
|
echo "RBENV_VERSION environment variable"
|
||||||
|
else
|
||||||
|
rbenv-version-file
|
||||||
|
fi
|
||||||
83
libexec/rbenv-versions
Executable file
83
libexec/rbenv-versions
Executable file
@@ -0,0 +1,83 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Summary: List installed Ruby versions
|
||||||
|
# Usage: rbenv versions [--bare] [--skip-aliases]
|
||||||
|
#
|
||||||
|
# Lists all Ruby versions found in `$RBENV_ROOT/versions/*'.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
unset bare
|
||||||
|
unset skip_aliases
|
||||||
|
# Provide rbenv completions
|
||||||
|
for arg; do
|
||||||
|
case "$arg" in
|
||||||
|
--complete )
|
||||||
|
echo --bare
|
||||||
|
echo --skip-aliases
|
||||||
|
exit ;;
|
||||||
|
--bare ) bare=1 ;;
|
||||||
|
--skip-aliases ) skip_aliases=1 ;;
|
||||||
|
* )
|
||||||
|
rbenv-help --usage versions >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
canonicalize_dir() {
|
||||||
|
{ cd "$1" && pwd -P
|
||||||
|
} 2>/dev/null || echo "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
versions_dir="${RBENV_ROOT}/versions"
|
||||||
|
if [ -n "$skip_aliases" ]; then
|
||||||
|
versions_dir="$(canonicalize_dir "$versions_dir")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
list_versions() {
|
||||||
|
local path
|
||||||
|
local target
|
||||||
|
shopt -s nullglob
|
||||||
|
for path in "$versions_dir"/*; do
|
||||||
|
if [ -d "$path" ]; then
|
||||||
|
if [ -n "$skip_aliases" ] && [ -L "$path" ]; then
|
||||||
|
target="$(canonicalize_dir "$path")"
|
||||||
|
[ "${target%/*}" != "$versions_dir" ] || continue
|
||||||
|
fi
|
||||||
|
echo "${path##*/}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
shopt -u nullglob
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -n "$bare" ]; then
|
||||||
|
list_versions
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
sort_versions() {
|
||||||
|
sed 'h; s/[+-]/./g; s/.p\([[:digit:]]\)/.z.\1/; s/$/.z/; G; s/\n/ /' | \
|
||||||
|
LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n | awk '{print $2}'
|
||||||
|
}
|
||||||
|
|
||||||
|
versions="$(
|
||||||
|
if RBENV_VERSION=system rbenv-which ruby >/dev/null 2>&1; then
|
||||||
|
echo system
|
||||||
|
fi
|
||||||
|
list_versions | sort_versions
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [ -z "$versions" ]; then
|
||||||
|
echo "Warning: no Ruby detected on the system" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
current_version="$(rbenv-version-name || true)"
|
||||||
|
while read -r version; do
|
||||||
|
if [ "$version" == "$current_version" ]; then
|
||||||
|
echo "* $(rbenv-version 2>/dev/null)"
|
||||||
|
else
|
||||||
|
echo " $version"
|
||||||
|
fi
|
||||||
|
done <<<"$versions"
|
||||||
38
libexec/rbenv-whence
Executable file
38
libexec/rbenv-whence
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Summary: List all Ruby versions that contain the given executable
|
||||||
|
# Usage: rbenv whence [--path] <command>
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$1" = "--complete" ]; then
|
||||||
|
echo --path
|
||||||
|
exec rbenv-shims --short
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" = "--path" ]; then
|
||||||
|
print_paths="1"
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
print_paths=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
whence() {
|
||||||
|
local command="$1"
|
||||||
|
rbenv-versions --bare | while read -r version; do
|
||||||
|
path="$(rbenv-prefix "$version")/bin/${command}"
|
||||||
|
if [ -x "$path" ]; then
|
||||||
|
[ "$print_paths" ] && echo "$path" || echo "$version"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
RBENV_COMMAND="$1"
|
||||||
|
if [ -z "$RBENV_COMMAND" ]; then
|
||||||
|
rbenv-help --usage whence >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
result="$(whence "$RBENV_COMMAND")"
|
||||||
|
[ -n "$result" ] && echo "$result"
|
||||||
74
libexec/rbenv-which
Executable file
74
libexec/rbenv-which
Executable file
@@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Summary: Display the full path to an executable
|
||||||
|
#
|
||||||
|
# Usage: rbenv which <command>
|
||||||
|
#
|
||||||
|
# Displays the full path to the executable that rbenv will invoke when
|
||||||
|
# you run the given command.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
[ -n "$RBENV_DEBUG" ] && set -x
|
||||||
|
|
||||||
|
# Provide rbenv completions
|
||||||
|
if [ "$1" = "--complete" ]; then
|
||||||
|
exec rbenv-shims --short
|
||||||
|
fi
|
||||||
|
|
||||||
|
remove_from_path() {
|
||||||
|
local path_to_remove="$1"
|
||||||
|
local path_before
|
||||||
|
local result=":${PATH//\~/$HOME}:"
|
||||||
|
while [ "$path_before" != "$result" ]; do
|
||||||
|
path_before="$result"
|
||||||
|
result="${result//:$path_to_remove:/:}"
|
||||||
|
done
|
||||||
|
result="${result%:}"
|
||||||
|
echo "${result#:}"
|
||||||
|
}
|
||||||
|
|
||||||
|
RBENV_COMMAND="$1"
|
||||||
|
|
||||||
|
if [ -z "$RBENV_COMMAND" ]; then
|
||||||
|
rbenv-help --usage which >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
RBENV_VERSION="${RBENV_VERSION:-$(rbenv-version-name)}"
|
||||||
|
|
||||||
|
if [ "$RBENV_VERSION" = "system" ]; then
|
||||||
|
PATH="$(remove_from_path "${RBENV_ROOT}/shims")" \
|
||||||
|
RBENV_COMMAND_PATH="$(command -v "$RBENV_COMMAND" || true)"
|
||||||
|
else
|
||||||
|
RBENV_COMMAND_PATH="${RBENV_ROOT}/versions/${RBENV_VERSION}/bin/${RBENV_COMMAND}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -x "$RBENV_COMMAND_PATH" && -n "$GEM_HOME" && -x "${GEM_HOME}/bin/${RBENV_COMMAND}" ]]; then
|
||||||
|
RBENV_COMMAND_PATH="${GEM_HOME}/bin/${RBENV_COMMAND}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=$'\n' read -d '' -r -a scripts <<<"$(rbenv-hooks which)" || true
|
||||||
|
for script in "${scripts[@]}"; do
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$script"
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -x "$RBENV_COMMAND_PATH" ]; then
|
||||||
|
echo "$RBENV_COMMAND_PATH"
|
||||||
|
elif [ "$RBENV_VERSION" != "system" ] && [ ! -d "${RBENV_ROOT}/versions/${RBENV_VERSION}" ]; then
|
||||||
|
echo "rbenv: version \`$RBENV_VERSION' is not installed (set by $(rbenv-version-origin))" >&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "rbenv: $RBENV_COMMAND: command not found" >&2
|
||||||
|
|
||||||
|
versions="$(rbenv-whence "$RBENV_COMMAND" || true)"
|
||||||
|
if [ -n "$versions" ]; then
|
||||||
|
{ echo
|
||||||
|
echo "The \`$1' command exists in these Ruby versions:"
|
||||||
|
echo "$versions" | sed 's/^/ /g'
|
||||||
|
echo
|
||||||
|
} >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
550
man/man1/pyenv.1
550
man/man1/pyenv.1
@@ -1,550 +0,0 @@
|
|||||||
.TH PYENV 1 "24 Apr 2023" "PYENV"
|
|
||||||
.SH NAME
|
|
||||||
pyenv \- Simple Python version management
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B pyenv
|
|
||||||
\fI\,<command> \/\fR[\fI\,<args>\/\fR]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
pyenv lets you easily switch between multiple versions of Python\. It's simple, unobtrusive, and follows the UNIX tradition of single\-purpose tools that do one thing well\.
|
|
||||||
.P
|
|
||||||
To start using pyenv
|
|
||||||
.IP "1." 3
|
|
||||||
\fBAppend\fR the following to \fB$HOME/.bashrc\fR
|
|
||||||
.P
|
|
||||||
.RS 15
|
|
||||||
.nf
|
|
||||||
if command -v pyenv 1>/dev/null 2>&1; then\n
|
|
||||||
eval "$(pyenv init -)" \n
|
|
||||||
fi
|
|
||||||
.fi
|
|
||||||
.RE
|
|
||||||
.RS 3
|
|
||||||
.P
|
|
||||||
.nh
|
|
||||||
Appending this line enables shims. Please make sure this line is placed toward the end of the shell configuration file since it manipulates \fBPATH\fR during the initialization\.
|
|
||||||
.hy
|
|
||||||
.TP 13
|
|
||||||
.B Debian note:
|
|
||||||
Modify only your \fB~/\.bashrc\fR file instead of creating
|
|
||||||
.br
|
|
||||||
\fB~/\.bash_profile\fR
|
|
||||||
.P
|
|
||||||
.RS 0
|
|
||||||
\fBZsh note\fR: Modify your \fB~/\.zshrc\fR file instead of \fB~/\.bashrc\fR
|
|
||||||
.P
|
|
||||||
\fBWarning\fR: If you configured your system so that \fBBASH_ENV\fR variable points to \fB\.bashrc\fR\. You should almost certainly put the above mentioned line into \fB\.bash_profile\fR, and \fBnot\fR into \fB\.bashrc\fR. Otherwise you may observe strange behaviour, such as \fBpyenv\fR getting into an infinite loop. See #264
|
|
||||||
.UR https://github\.com/pyenv/pyenv/issues/264
|
|
||||||
.UE
|
|
||||||
for details.
|
|
||||||
.RE
|
|
||||||
.RE
|
|
||||||
.IP "2." 3
|
|
||||||
\fBRestart your shell so the path changes take effect\.\fR You can now begin using pyenv\.
|
|
||||||
.P
|
|
||||||
.RS 15
|
|
||||||
exec "$SHELL"\fR
|
|
||||||
.RE
|
|
||||||
.IP "3." 3
|
|
||||||
\fBInstall Python versions into \fB$(pyenv root)/versions\fR\.\fR For example, to download and install Python 3\.6\.12, run:
|
|
||||||
.P
|
|
||||||
.RS 15
|
|
||||||
.B pyenv install 3.6.12\fR
|
|
||||||
.RE
|
|
||||||
.P
|
|
||||||
\fBNOTE:\fR If you need to pass configure option to build, please use \fBCONFIGURE_OPTS\fR environment variable. If you are having trouble installing a python version, please visit the wiki page about Common Build Problems
|
|
||||||
.UR https://github\.com/pyenv/pyenv/wiki/Common\-build\-problems
|
|
||||||
.UE
|
|
||||||
.P
|
|
||||||
\fBProxy note\fR: If you use a proxy, export \fBHTTP_PROXY\fR and \fBHTTPS_PROXY\fR environment variables.
|
|
||||||
.P
|
|
||||||
.SS "Stop using pyenv"
|
|
||||||
The simplicity of pyenv makes it easy to temporarily disable it, or uninstall from the system\.
|
|
||||||
To \fBdisable\fR pyenv managing your Python versions, simply remove the \fBpyenv init\fR line from your shell startup configuration\. This will remove pyenv shims directory from PATH, and future invocations like \fBpython\fR will execute the system Python version, as before pyenv\.
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
\fBpyenv\fR will still be accessible on the command line, but your Python apps won't be affected by version switching\.
|
|
||||||
.IP "" 0
|
|
||||||
.SH COMMAND LINE OPTIONS
|
|
||||||
Like \fBgit\fR, the \fBpyenv\fR command delegates to subcommands based on its first argument\.
|
|
||||||
.SS "Some useful pyenv commands are:"
|
|
||||||
.TP 5
|
|
||||||
.B commands
|
|
||||||
List all available pyenv commands
|
|
||||||
.TP
|
|
||||||
.B exec
|
|
||||||
Run an executable with the selected Python version
|
|
||||||
.TP
|
|
||||||
.B global
|
|
||||||
Set or show the global Python version(s)
|
|
||||||
.TP
|
|
||||||
.B help
|
|
||||||
Display help for a command
|
|
||||||
.TP
|
|
||||||
.B hooks
|
|
||||||
List hook scripts for a given pyenv command
|
|
||||||
.TP
|
|
||||||
.B init
|
|
||||||
Configure the shell environment for pyenv
|
|
||||||
.TP
|
|
||||||
.B install
|
|
||||||
Install a Python version using python\-build
|
|
||||||
.TP
|
|
||||||
.B local
|
|
||||||
Set or show the local application\-specific Python version(s)
|
|
||||||
.TP
|
|
||||||
.B prefix
|
|
||||||
Display prefix for a Python version
|
|
||||||
.TP
|
|
||||||
.B rehash
|
|
||||||
Rehash pyenv shims (run this after installing executables)
|
|
||||||
.TP
|
|
||||||
.B root
|
|
||||||
Display the root directory where versions and shims are kept
|
|
||||||
.TP
|
|
||||||
.B shell
|
|
||||||
Set or show the shell\-specific Python version
|
|
||||||
.TP
|
|
||||||
.B shims
|
|
||||||
List existing pyenv shims
|
|
||||||
.TP
|
|
||||||
.B uninstall
|
|
||||||
Uninstall Python versions
|
|
||||||
.TP
|
|
||||||
.B version
|
|
||||||
Show the current Python version(s) and its origin
|
|
||||||
.TP
|
|
||||||
.B version\-file
|
|
||||||
Detect the file that sets the current pyenv version
|
|
||||||
.TP
|
|
||||||
.B version\-name
|
|
||||||
Show the current Python version
|
|
||||||
.TP
|
|
||||||
.B version\-origin
|
|
||||||
Explain how the current Python version is set
|
|
||||||
.TP
|
|
||||||
.B versions
|
|
||||||
List all Python versions available to pyenv
|
|
||||||
.TP
|
|
||||||
.B whence
|
|
||||||
List all Python versions that contain the given executable
|
|
||||||
.TP
|
|
||||||
.B which
|
|
||||||
Display the full path to an executable
|
|
||||||
.PP
|
|
||||||
See `pyenv help <command>' for information on a specific command.
|
|
||||||
For full documentation, see \fBCOMMAND REFERENCE\fR section
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.B \-h, \-\-help
|
|
||||||
Show summary of options.
|
|
||||||
.TP
|
|
||||||
.B \-v, \-\-version
|
|
||||||
Show version of program.
|
|
||||||
.SH COMPARISON
|
|
||||||
.P
|
|
||||||
.B "pyenv does\|\.\|\.\|\.
|
|
||||||
.P
|
|
||||||
.IP \(bu 4
|
|
||||||
Let you \fBchange the global Python version\fR on a per\-user basis\.
|
|
||||||
.IP \(bu 4
|
|
||||||
Provide support for \fBper\-project Python versions\fR\.
|
|
||||||
.IP \(bu 4
|
|
||||||
Allow you to \fBoverride the Python version\fR with an environment variable\.
|
|
||||||
.IP \(bu 4
|
|
||||||
Search commands from \fBmultiple versions of Python at a time\fR\. This may be helpful to test across Python versions with tox
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
.B "In contrast with pythonbrew and pythonz, pyenv does not\|\.\|\.\|\."
|
|
||||||
.IP \(bu 4
|
|
||||||
\fBDepend on Python itself\.\fR pyenv was made from pure shell scripts\. There is no bootstrap problem of Python\.
|
|
||||||
.IP \(bu 4
|
|
||||||
\fBNeed to be loaded into your shell\.\fR Instead, pyenv's shim approach works by adding a directory to your \fB$PATH\fR\.
|
|
||||||
.IP \(bu 4
|
|
||||||
\fBManage virtualenv\.\fR Of course, you can create virtualenv yourself, or pyenv\-virtualenv to automate the process\.
|
|
||||||
.SH "How It Works"
|
|
||||||
At a high level, pyenv intercepts Python commands using shim executables injected into your \fBPATH\fR, determines which Python version has been specified by your application, and passes your commands along to the correct Python installation\.
|
|
||||||
.SS "Understanding PATH"
|
|
||||||
When you run a command like \fBpython\fR or \fBpip\fR, your operating system searches through a list of directories to find an executable file with that name\. This list of directories lives in an environment variable called \fBPATH\fR, with each directory in the list separated by a colon:
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
/usr/local/bin:/usr/bin:/bin
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
Directories in \fBPATH\fR are searched from left to right, so a matching executable in a directory at the beginning of the list takes precedence over another one at the end\. In this example, the \fB/usr/local/bin\fR directory will be searched first, then \fB/usr/bin\fR, then \fB/bin\fR\.
|
|
||||||
.SS "Understanding Shims"
|
|
||||||
pyenv works by inserting a directory of \fIshims\fR at the front of your \fBPATH\fR:
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$(pyenv root)/shims:/usr/local/bin:/usr/bin:/bin
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
Through a process called \fIrehashing\fR, pyenv maintains shims in that directory to match every Python command (\fBpython\fR,\fBpip\fR,etc...) across every installed version of Python
|
|
||||||
.P
|
|
||||||
Shims are lightweight executables that simply pass your command along to pyenv\. So with pyenv installed, when you run, say, \fBpip\fR, your operating system will do the following:
|
|
||||||
.IP \(bu 4
|
|
||||||
Search your \fBPATH\fR for an executable file named \fBpip\fR
|
|
||||||
.IP \(bu 4
|
|
||||||
Find the pyenv shim named \fBpip\fR at the beginning of your \fBPATH\fR
|
|
||||||
.IP \(bu 4
|
|
||||||
Run the shim named \fBpip\fR, which in turn passes the command along to pyenv
|
|
||||||
.IP "" 0
|
|
||||||
.SS "Choosing the Python Version"
|
|
||||||
When you execute a shim, pyenv determines which Python version to use by reading it from the following sources, in this order:
|
|
||||||
.IP "1." 4
|
|
||||||
The \fBPYENV_VERSION\fR environment variable (if specified)\. You can use the \fBpyenv shell\fR command to set this environment variable in your current shell session\.
|
|
||||||
.IP "2." 4
|
|
||||||
The application\-specific \fB\.python\-version\fR file in the current directory (if present)\. You can modify the current directory's \fB\.python\-version\fR file with the \fBpyenv local\fR command\.
|
|
||||||
.IP "3." 4
|
|
||||||
The first \fB\.python\-version\fR file found (if any) by searching each parent directory, until reaching the root of your filesystem\.
|
|
||||||
.IP "4." 4
|
|
||||||
The global \fB$(pyenv root)/version\fR file\. You can modify this file using the \fBpyenv global\fR command\. If the global version file is not present, pyenv assumes you want to use the "system" Python\. (In other words, whatever version would run if pyenv weren't in your \fBPATH\fR\.)
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
.nh
|
|
||||||
\fBNOTE:\fR You can activate multiple versions at the same time, including multiple versions of Python2 or Python3 simultaneously\. This allows for parallel usage of Python2 and Python3, and is required with tools like \fBtox\fR\. For example, to set your path to first use your \fBsystem\fR Python and Python3 (set to 2\.7\.9 and 3\.4\.2 in this example), but also have Python 3\.3\.6, 3\.2, and 2\.5 available on your \fBPATH\fR, one would first \fBpyenv install\fR the missing versions, then set \fBpyenv global system 3\.3\.6 3\.2 2\.5\fR\. At this point, one should be able to find the full executable path to each of these using \fBpyenv which\fR, e\.g\. \fBpyenv which python2\.5\fR (should display \fB$(pyenv root)/versions/2\.5/bin/python2\.5\fR), or \fBpyenv which python3\.4\fR (should display path to system Python3)\. You can also specify multiple versions in a \fB\.python\-version\fR file, separated by newlines or any whitespace\.
|
|
||||||
hy
|
|
||||||
.SS "Locating the Python Installation"
|
|
||||||
Once pyenv has determined which version of Python your application has specified, it passes the command along to the corresponding Python installation\.
|
|
||||||
.P
|
|
||||||
Each Python version is installed into its own directory under
|
|
||||||
.nf
|
|
||||||
\fB$(pyenv root)/versions\fR\.
|
|
||||||
.fi
|
|
||||||
.P
|
|
||||||
For example, you might have these versions installed:
|
|
||||||
.IP \(bu 4
|
|
||||||
\fB$(pyenv root)/versions/2\.7\.8/\fR
|
|
||||||
.IP \(bu 4
|
|
||||||
\fB$(pyenv root)/versions/3\.4\.2/\fR
|
|
||||||
.IP \(bu 4
|
|
||||||
\fB$(pyenv root)/versions/pypy\-2\.4\.0/\fR
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
As far as pyenv is concerned, version names are simply the directories in \fB$(pyenv root)/versions\fR\.
|
|
||||||
.SS "Managing Virtual Environments"
|
|
||||||
There is a pyenv plugin named pyenv\-virtualenv which comes with various features to help pyenv users to manage virtual environments created by virtualenv or Anaconda\. Because the \fBactivate\fR script of those virtual environments are relying on mutating \fB$PATH\fR variable of user's interactive shell, it will intercept pyenv's shim style command execution hooks\. We'd recommend to install pyenv\-virtualenv as well if you have some plan to play with those virtual environments\.
|
|
||||||
|
|
||||||
.SH "Advanced Configuration"
|
|
||||||
Skip this section unless you must know what every line in your shell profile is doing\.
|
|
||||||
.P
|
|
||||||
\fBpyenv init\fR is the only command that crosses the line of loading extra commands into your shell\. Coming from rvm, some of you might be opposed to this idea\. Here's what \fBpyenv init\fR actually does:
|
|
||||||
.IP "1." 4
|
|
||||||
\fBSets up your shims path\.\fR This is the only requirement for pyenv to function properly\. You can do this by hand by prepending \fB$(pyenv root)/shims\fR to your \fB$PATH\fR\.
|
|
||||||
.IP "2." 4
|
|
||||||
\fBRehashes shims\.\fR From time to time you'll need to rebuild your shim files\. Doing this on init makes sure everything is up to date\. You can always run \fBpyenv rehash\fR manually\.
|
|
||||||
You can disable this functionality by adding \fB--no-rehash\fR to the end of your \fBpyenv init\fR command line.
|
|
||||||
.IP "3." 4
|
|
||||||
\fBInstalls the sh dispatcher\.\fR This bit is also optional, but allows pyenv and plugins to change variables in your current shell, making commands like \fBpyenv shell\fR possible\. The sh dispatcher doesn't do anything crazy like override \fBcd\fR or hack your shell prompt, but if for some reason you need \fBpyenv\fR to be a real script rather than a shell function, you can safely skip it\.
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
To see exactly what happens under the hood for yourself, run \fB"pyenv init \-"\fR\.
|
|
||||||
.SH "Uninstalling Python Versions"
|
|
||||||
As time goes on, you will accumulate Python versions in your \fB$(pyenv root)/versions\fR directory\.
|
|
||||||
.P
|
|
||||||
To remove old Python versions, \fBpyenv uninstall\fR command to automate the removal process\.
|
|
||||||
.P
|
|
||||||
Alternatively, simply \fBrm \-rf\fR the directory of the version you want to remove\. You can find the directory of a particular Python version with the \fBpyenv prefix\fR command,
|
|
||||||
.P
|
|
||||||
e\.g\. \fBpyenv prefix 2\.6\.8\fR\.
|
|
||||||
.SH "Command Reference"
|
|
||||||
.P
|
|
||||||
The most common subcommands are:
|
|
||||||
.SS "pyenv commands"
|
|
||||||
Lists all available pyenv commands\.
|
|
||||||
.SS "pyenv local"
|
|
||||||
Sets a local application\-specific Python version by writing the version name to a \fB\.python\-version\fR file in the current directory\. This version overrides the global version, and can be overridden itself by setting the \fBPYENV_VERSION\fR environment variable or with the \fBpyenv shell\fR command\.
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv local 2\.7\.6
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
When run without a version number, \fBpyenv local\fR reports the currently configured local version\. You can also unset the local version:
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv local \-\-unset
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
Previous versions of pyenv stored local version specifications in a file named \fB\.pyenv\-version\fR\. For backwards compatibility, pyenv will read a local version specified in an \fB\.pyenv\-version\fR file, but a \fB\.python\-version\fR file in the same directory will take precedence\.
|
|
||||||
.P
|
|
||||||
You can specify multiple versions as local Python at once\.
|
|
||||||
.P
|
|
||||||
Let's say if you have two versions of 2\.7\.6 and 3\.3\.3\. If you prefer 2\.7\.6 over 3\.3\.3,
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv local 2\.7\.6 3\.3\.3
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2\.7\.6 (set by /Users/yyuu/path/to/project/\.python\-version)
|
|
||||||
* 3\.3\.3 (set by /Users/yyuu/path/to/project/\.python\-version)
|
|
||||||
$ python \-\-version
|
|
||||||
Python 2\.7\.6
|
|
||||||
$ python2\.7 \-\-version
|
|
||||||
Python 2\.7\.6
|
|
||||||
$ python3\.3 \-\-version
|
|
||||||
Python 3\.3\.3
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
or, if you prefer 3\.3\.3 over 2\.7\.6,
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv local 3\.3\.3 2\.7\.6
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2\.7\.6 (set by /Users/yyuu/path/to/project/\.python\-version)
|
|
||||||
* 3\.3\.3 (set by /Users/yyuu/path/to/project/\.python\-version)
|
|
||||||
venv27
|
|
||||||
$ python \-\-version
|
|
||||||
Python 3\.3\.3
|
|
||||||
$ python2\.7 \-\-version
|
|
||||||
Python 2\.7\.6
|
|
||||||
$ python3\.3 \-\-version
|
|
||||||
Python 3\.3\.3
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.SS "pyenv global"
|
|
||||||
Sets the global version of Python to be used in all shells by writing the version name to the \fB~/\.pyenv/version\fR file\. This version can be overridden by an application\-specific \fB\.python\-version\fR file, or by setting the \fBPYENV_VERSION\fR environment variable\.
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv global 2\.7\.6
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
The special version name \fBsystem\fR tells pyenv to use the system Python (detected by searching your \fB$PATH\fR)\.
|
|
||||||
.P
|
|
||||||
When run without a version number, \fBpyenv global\fR reports the currently configured global version\.
|
|
||||||
.P
|
|
||||||
You can specify multiple versions as global Python at once\.
|
|
||||||
.P
|
|
||||||
Let's say if you have two versions of 2\.7\.6 and 3\.3\.3\. If you prefer 2\.7\.6 over 3\.3\.3,
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv global 2\.7\.6 3\.3\.3
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2\.7\.6 (set by /Users/yyuu/\.pyenv/version)
|
|
||||||
* 3\.3\.3 (set by /Users/yyuu/\.pyenv/version)
|
|
||||||
$ python \-\-version
|
|
||||||
Python 2\.7\.6
|
|
||||||
$ python2\.7 \-\-version
|
|
||||||
Python 2\.7\.6
|
|
||||||
$ python3\.3 \-\-version
|
|
||||||
Python 3\.3\.3
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
or, if you prefer 3\.3\.3 over 2\.7\.6,
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv global 3\.3\.3 2\.7\.6
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2\.7\.6 (set by /Users/yyuu/\.pyenv/version)
|
|
||||||
* 3\.3\.3 (set by /Users/yyuu/\.pyenv/version)
|
|
||||||
venv27
|
|
||||||
$ python \-\-version
|
|
||||||
Python 3\.3\.3
|
|
||||||
$ python2\.7 \-\-version
|
|
||||||
Python 2\.7\.6
|
|
||||||
$ python3\.3 \-\-version
|
|
||||||
Python 3\.3\.3
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.SS "pyenv shell"
|
|
||||||
Sets a shell\-specific Python version by setting the \fBPYENV_VERSION\fR environment variable in your shell\. This version overrides application\-specific versions and the global version\.
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv shell pypy\-2\.2\.1
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
When run without a version number, \fBpyenv shell\fR reports the current value of \fBPYENV_VERSION\fR\. You can also unset the shell version:
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv shell \-\-unset
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
Note that you'll need pyenv's shell integration enabled (step 3 of the installation instructions) in order to use this command\. If you prefer not to use shell integration, you may simply set the \fBPYENV_VERSION\fR variable yourself:
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ export PYENV_VERSION=pypy\-2\.2\.1
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
You can specify multiple versions via \fBPYENV_VERSION\fR at once\.
|
|
||||||
.P
|
|
||||||
Let's say if you have two versions of 2\.7\.6 and 3\.3\.3\. If you prefer 2\.7\.6 over 3\.3\.3,
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv shell 2\.7\.6 3\.3\.3
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2\.7\.6 (set by PYENV_VERSION environment variable)
|
|
||||||
* 3\.3\.3 (set by PYENV_VERSION environment variable)
|
|
||||||
$ python \-\-version
|
|
||||||
Python 2\.7\.6
|
|
||||||
$ python2\.7 \-\-version
|
|
||||||
Python 2\.7\.6
|
|
||||||
$ python3\.3 \-\-version
|
|
||||||
Python 3\.3\.3
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
or, if you prefer 3\.3\.3 over 2\.7\.6,
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv shell 3\.3\.3 2\.7\.6
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
* 2\.7\.6 (set by PYENV_VERSION environment variable)
|
|
||||||
* 3\.3\.3 (set by PYENV_VERSION environment variable)
|
|
||||||
venv27
|
|
||||||
$ python \-\-version
|
|
||||||
Python 3\.3\.3
|
|
||||||
$ python2\.7 \-\-version
|
|
||||||
Python 2\.7\.6
|
|
||||||
$ python3\.3 \-\-version
|
|
||||||
Python 3\.3\.3
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.SS "pyenv install"
|
|
||||||
Install a Python version
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
Usage: pyenv install [\-f] [\-kvp] <version>
|
|
||||||
pyenv install [\-f] [\-kvp] <definition\-file>
|
|
||||||
pyenv install \-l|\-\-list
|
|
||||||
|
|
||||||
\-l, \-\-list List all available versions
|
|
||||||
\-f, \-\-force Install even if the version appears to be installed
|
|
||||||
already
|
|
||||||
\-s, \-\-skip\-existing Skip the installation if the version appears to be
|
|
||||||
installed already
|
|
||||||
|
|
||||||
python\-build options:
|
|
||||||
|
|
||||||
\-k, \-\-keep Keep source tree in $PYENV_BUILD_ROOT after installation
|
|
||||||
(defaults to $PYENV_ROOT/sources)
|
|
||||||
\-v, \-\-verbose Verbose mode: print compilation status to stdout
|
|
||||||
\-p, \-\-patch Apply a patch from stdin before building
|
|
||||||
\-g, \-\-debug Build a debug version
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
To list the all available versions of Python, including Anaconda, Jython, pypy, and stackless, use:
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv install \-\-list
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.P
|
|
||||||
Then install the desired versions:
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv install 2\.7\.6
|
|
||||||
$ pyenv install 2\.6\.8
|
|
||||||
$ pyenv versions
|
|
||||||
system
|
|
||||||
2\.6\.8
|
|
||||||
* 2\.7\.6 (set by /home/yyuu/\.pyenv/version)
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.SS "pyenv uninstall"
|
|
||||||
Uninstall Python versions\.
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
Usage: pyenv uninstall [\-f|\-\-force] <version> ...
|
|
||||||
|
|
||||||
\-f Attempt to remove the specified version without prompting
|
|
||||||
for confirmation\. If the version does not exist, do not
|
|
||||||
display an error message\.
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.SS "pyenv rehash"
|
|
||||||
Installs shims for all Python binaries known to pyenv (i\.e\., \fB~/\.pyenv/versions/*/bin/*\fR)\. Run this command after you install a new version of Python, or install a package that provides binaries\.
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv rehash
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.SS "pyenv version"
|
|
||||||
Displays the currently active Python version, along with information on how it was set\.
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv version
|
|
||||||
2\.7\.6 (set by /home/yyuu/\.pyenv/version)
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.SS "pyenv versions"
|
|
||||||
Lists all Python versions known to pyenv, and shows an asterisk next to the currently active version\.
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv versions
|
|
||||||
2\.5\.6
|
|
||||||
2\.6\.8
|
|
||||||
* 2\.7\.6 (set by /home/yyuu/\.pyenv/version)
|
|
||||||
3\.3\.3
|
|
||||||
jython\-2\.5\.3
|
|
||||||
pypy\-2\.2\.1
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.SS "pyenv which"
|
|
||||||
Displays the full path to the executable that pyenv will invoke when you run the given command\.
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv which python3\.3
|
|
||||||
/home/yyuu/\.pyenv/versions/3\.3\.3/bin/python3\.3
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.SS "pyenv whence"
|
|
||||||
Lists all Python versions with the given command installed\.
|
|
||||||
.IP "" 4
|
|
||||||
.nf
|
|
||||||
$ pyenv whence 2to3
|
|
||||||
2\.6\.8
|
|
||||||
2\.7\.6
|
|
||||||
3\.3\.3
|
|
||||||
.fi
|
|
||||||
.IP "" 0
|
|
||||||
.SH "Environment variables"
|
|
||||||
You can affect how pyenv operates with the following settings:
|
|
||||||
.TP 28
|
|
||||||
.B name (default)
|
|
||||||
.B description
|
|
||||||
.TP 28
|
|
||||||
.B PYENV_VERSION
|
|
||||||
Specifies the Python version to be used. Also see \fBpyenv shell\fR
|
|
||||||
.TP
|
|
||||||
.B PYENV_ROOT (\fB~/.pyenv\fR)
|
|
||||||
Defines the directory under which Python versions and shims reside. Also see \fBpyenv root\fR
|
|
||||||
.TP
|
|
||||||
.B PYENV_DEBUG
|
|
||||||
Outputs debug information.
|
|
||||||
.br
|
|
||||||
Also as: \fBpyenv --debug <subcommand>\fR
|
|
||||||
.TP
|
|
||||||
.B PYENV_HOOK_PATH
|
|
||||||
Colon\-separated list of paths searched for pyenv hooks\.
|
|
||||||
.TP
|
|
||||||
.B PYENV_DIR (\fB$PWD\fR)
|
|
||||||
Directory to start searching for \fB\.python\-version\fR files\.
|
|
||||||
.TP
|
|
||||||
.B HTTP_PROXY,HTTPS_PROXY
|
|
||||||
Proxy Variables
|
|
||||||
.TP
|
|
||||||
.B CONFIGURE_OPTS
|
|
||||||
Pass configure options to build.
|
|
||||||
.TP
|
|
||||||
.B PYTHON_BUILD_ARIA2_OPTS
|
|
||||||
Used to pass additional parameters to \fBaria2\fR
|
|
||||||
.UR https://aria2\.github\.io/
|
|
||||||
.UE
|
|
||||||
If the \fBaria2c\fR binary is available on PATH, pyenv uses \fBaria2c\fR instead of \fBcurl\fR or \fBwget\fR to download the Python Source code\. If you have an unstable internet connection, you can use this variable to instruct \fBaria2\fR to accelerate the download\.
|
|
||||||
In most cases, you will only need to use \fB\-x 10 \-k 1M\fR as value to \fBPYTHON_BUILD_ARIA2_OPTS\fR environment variable
|
|
||||||
.SH "License"
|
|
||||||
The \fBMIT\fR License
|
|
||||||
5
plugins/.gitignore
vendored
5
plugins/.gitignore
vendored
@@ -1,5 +0,0 @@
|
|||||||
/*
|
|
||||||
!/.gitignore
|
|
||||||
!/version-ext-compat
|
|
||||||
!/python-build
|
|
||||||
/python-build/test/build
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
Copyright (c) 2013 Yamashita, Yuu
|
|
||||||
Copyright (c) 2012-2013 Sam Stephenson
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
of the Software, and to permit persons to whom the Software is furnished to do
|
|
||||||
so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -1,339 +0,0 @@
|
|||||||
# python-build
|
|
||||||
|
|
||||||
python-build is a [pyenv](https://github.com/pyenv/pyenv) plugin that
|
|
||||||
provides a `pyenv install` command to compile and install different versions
|
|
||||||
of Python on UNIX-like systems.
|
|
||||||
|
|
||||||
You can also use python-build without pyenv in environments where you need
|
|
||||||
precise control over Python version installation.
|
|
||||||
|
|
||||||
See the [list of releases](https://github.com/pyenv/pyenv/releases)
|
|
||||||
for changes in each version.
|
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### Installing as a pyenv plugin (recommended)
|
|
||||||
|
|
||||||
Since python-build is bundled with pyenv by
|
|
||||||
default, you do not need to do anything.
|
|
||||||
|
|
||||||
### Installing as a standalone program (advanced)
|
|
||||||
|
|
||||||
Installing python-build as a standalone program will give you access to the
|
|
||||||
`python-build` command for precise control over Python version installation. If you
|
|
||||||
have pyenv installed, you will also be able to use the `pyenv install` command.
|
|
||||||
|
|
||||||
git clone https://github.com/pyenv/pyenv.git
|
|
||||||
cd pyenv/plugins/python-build
|
|
||||||
./install.sh
|
|
||||||
|
|
||||||
This will install python-build into `/usr/local`. If you do not have write
|
|
||||||
permission to `/usr/local`, you will need to run `sudo ./install.sh` instead.
|
|
||||||
You can install to a different prefix by setting the `PREFIX` environment
|
|
||||||
variable.
|
|
||||||
|
|
||||||
To update python-build after it has been installed, run `git pull` in your cloned
|
|
||||||
copy of the repository, then re-run the install script.
|
|
||||||
|
|
||||||
### Installing with Homebrew (for OS X users)
|
|
||||||
|
|
||||||
Mac OS X users can install python-build with the [Homebrew](http://brew.sh)
|
|
||||||
package manager. This will give you access to the `python-build` command. If you
|
|
||||||
have pyenv installed, you will also be able to use the `pyenv install` command.
|
|
||||||
|
|
||||||
*This is the recommended method of installation if you installed pyenv with
|
|
||||||
Homebrew.*
|
|
||||||
|
|
||||||
brew install pyenv
|
|
||||||
|
|
||||||
Or, if you would like to install the latest development release:
|
|
||||||
|
|
||||||
brew install --HEAD pyenv
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Before you begin, you should ensure that your build environment has the proper
|
|
||||||
system dependencies for compiling the wanted Python Version (see our [recommendations](https://github.com/pyenv/pyenv/wiki#suggested-build-environment)).
|
|
||||||
|
|
||||||
### Using `pyenv install` with pyenv
|
|
||||||
|
|
||||||
To install a Python version for use with pyenv, run `pyenv install` with
|
|
||||||
exact name of the version you want to install. For example,
|
|
||||||
|
|
||||||
pyenv install 2.7.4
|
|
||||||
|
|
||||||
Python versions will be installed into a directory of the same name under
|
|
||||||
`~/.pyenv/versions`.
|
|
||||||
|
|
||||||
To see a list of all available Python versions, run `pyenv install --list`. You
|
|
||||||
may also tab-complete available Python versions if your pyenv installation is
|
|
||||||
properly configured.
|
|
||||||
|
|
||||||
### Using `python-build` standalone
|
|
||||||
|
|
||||||
If you have installed python-build as a standalone program, you can use the
|
|
||||||
`python-build` command to compile and install Python versions into specific
|
|
||||||
locations.
|
|
||||||
|
|
||||||
Run the `python-build` command with the exact name of the version you want to
|
|
||||||
install and the full path where you want to install it. For example,
|
|
||||||
|
|
||||||
python-build 2.7.4 ~/local/python-2.7.4
|
|
||||||
|
|
||||||
To see a list of all available Python versions, run `python-build --definitions`.
|
|
||||||
|
|
||||||
Pass the `-v` or `--verbose` flag to `python-build` as the first argument to see
|
|
||||||
what's happening under the hood.
|
|
||||||
|
|
||||||
### Custom definitions
|
|
||||||
|
|
||||||
Both `pyenv install` and `python-build` accept a path to a custom definition file
|
|
||||||
in place of a version name. Custom definitions let you develop and install
|
|
||||||
versions of Python that are not yet supported by python-build.
|
|
||||||
|
|
||||||
See the [python-build built-in definitions](https://github.com/pyenv/pyenv/tree/master/plugins/python-build/share/python-build) as a starting point for
|
|
||||||
custom definition files.
|
|
||||||
|
|
||||||
[definitions]: https://github.com/pyenv/pyenv/tree/master/plugins/python-build/share/python-build
|
|
||||||
|
|
||||||
### Default build configuration
|
|
||||||
|
|
||||||
Without the user customizing the build with environment variables (see below),
|
|
||||||
`python-build` builds Python with mostly default Configure options
|
|
||||||
to maintain the principle of the least surprise.
|
|
||||||
|
|
||||||
The exceptions -- non-default options that are set by default -- are listed below:
|
|
||||||
|
|
||||||
| Option/Behavior | Rationale |
|
|
||||||
|-----------------|-----------|
|
|
||||||
| `--enable-shared` is on by default. Pass `--disable-shared` to Configure options to override | The official CPython Docker image uses it. It's required to embed CPython. |
|
|
||||||
| argument to `--enable-universalsdk` is ignored and set to `/` |
|
|
||||||
| `--with-universal-archs` defaults to `universal2` on ARM64 architecture | the only dual-architecture Macs in use today are Apple Silicon which can only build that one |
|
|
||||||
| argument to `--enable-framework` is ignored and set to a specific value | CPython's build logic requires a very specific argument to avoid installing the `Applications` part globally |
|
|
||||||
| argument to `--enable-unicode` in non-MacOS is overridden to `ucs4` for 2.x-3.3 |
|
|
||||||
| `MACOSX_DEPLOYMENT_TARGET` defaults to the running MacOS version |
|
|
||||||
|
|
||||||
|
|
||||||
#### Integration with 3rd-party package ecosystems
|
|
||||||
|
|
||||||
##### Homebrew
|
|
||||||
|
|
||||||
Homebrew is used to find dependency packages if `brew` is found on `PATH`:
|
|
||||||
* In MacOS, or
|
|
||||||
* If the running Pyenv itself is installed with Homebrew
|
|
||||||
|
|
||||||
Set `PYTHON_BUILD_USE_HOMEBREW` or `PYTHON_BUILD_SKIP_HOMEBREW` to override this default.
|
|
||||||
|
|
||||||
When Homebrew is used, its `include` and `lib` paths are added to compiler search path (the latter is also set as `rpath`),
|
|
||||||
and also Python dependencies that are typically keg-only are searched for in the Homebrew installation and added individually.
|
|
||||||
|
|
||||||
**NOTE:** Homebrew is not used in Linux by default because it's rolling-release which causes a problem.
|
|
||||||
Upgrading a Python dependency in Homebrew to a new major version (that `brew` does without warning)
|
|
||||||
would break all Pyenv-managed installations that depend on it.
|
|
||||||
You can use a [community plugin `fix-version`](https://github.com/pyenv/pyenv/wiki/Plugins#community-plugins)
|
|
||||||
to fix installations in such a case.
|
|
||||||
|
|
||||||
##### Portage
|
|
||||||
|
|
||||||
In FreeBSD, if `pkg` is on PATH, Ports are searched for some dependencies that Configure is known to not search for via `pkg-config`.
|
|
||||||
(Later versions of CPython search for more packages via `pkg-config` so this may eventually become redundant.)
|
|
||||||
|
|
||||||
|
|
||||||
### Special environment variables
|
|
||||||
|
|
||||||
You can set certain environment variables to control the build process.
|
|
||||||
|
|
||||||
* `TMPDIR` sets the location where python-build stores temporary files.
|
|
||||||
* `PYTHON_BUILD_BUILD_PATH` sets the location in which sources are downloaded and
|
|
||||||
built. By default, this is a subdirectory of `TMPDIR`.
|
|
||||||
* `PYTHON_BUILD_CACHE_PATH`, if set, specifies a directory to use for caching
|
|
||||||
downloaded package files.
|
|
||||||
* `PYTHON_BUILD_MIRROR_URL` overrides the default mirror URL root to one of your
|
|
||||||
choosing.
|
|
||||||
* `PYTHON_BUILD_MIRROR_URL_SKIP_CHECKSUM`, if set, does not append the SHA2
|
|
||||||
checksum of the file to the mirror URL.
|
|
||||||
* `PYTHON_BUILD_SKIP_MIRROR`, if set, forces python-build to download packages from
|
|
||||||
their original source URLs instead of using a mirror.
|
|
||||||
* `PYTHON_BUILD_HTTP_CLIENT`, explicitly specify the HTTP client type to use. `aria2`, `curl` and `wget` are the supported values and by default, are searched in that order.
|
|
||||||
* `PYTHON_BUILD_CURL_OPTS`, `PYTHON_BUILD_WGET_OPTS`, `PYTHON_BUILD_ARIA2_OPTS` pass additional parameters to the corresponding HTTP client.
|
|
||||||
* `PYTHON_BUILD_SKIP_HOMEBREW`, if set, will not search for libraries installed by Homebrew when it would normally will.
|
|
||||||
* `PYTHON_BUILD_USE_HOMEBREW`, if set, will search for libraries installed by Homebrew when it would normally not.
|
|
||||||
* `PYTHON_BUILD_HOMEBREW_OPENSSL_FORMULA`, override the Homebrew OpenSSL formula to use.
|
|
||||||
* `PYTHON_BUILD_ROOT` overrides the default location from where build definitions
|
|
||||||
in `share/python-build/` are looked up.
|
|
||||||
* `PYTHON_BUILD_DEFINITIONS` can be a list of colon-separated paths that get
|
|
||||||
additionally searched when looking up build definitions.
|
|
||||||
* `CC` sets the path to the C compiler.
|
|
||||||
* `PYTHON_CFLAGS` lets you pass additional options to the default `CFLAGS`. Use
|
|
||||||
this to override, for instance, the `-O3` option.
|
|
||||||
* `CONFIGURE_OPTS` lets you pass additional options to `./configure`.
|
|
||||||
* `MAKE` lets you override the command to use for `make`. Useful for specifying
|
|
||||||
GNU make (`gmake`) on some systems.
|
|
||||||
* `MAKE_OPTS` (or `MAKEOPTS`) lets you pass additional options to `make`.
|
|
||||||
* `MAKE_INSTALL_OPTS` lets you pass additional options to `make install`.
|
|
||||||
* `PYTHON_CONFIGURE_OPTS` and `PYTHON_MAKE_OPTS` and `PYTHON_MAKE_INSTALL_OPTS` allow
|
|
||||||
you to specify configure and make options for building CPython. These variables
|
|
||||||
will be passed to Python only, not any dependent packages (e.g. libyaml).
|
|
||||||
|
|
||||||
### Applying patches to Python before compiling
|
|
||||||
|
|
||||||
Both `pyenv install` and `python-build` support the `--patch` (`-p`) flag that
|
|
||||||
signals that a patch from stdin should be applied to Python, Jython or PyPy
|
|
||||||
source code before the `./configure` and compilation steps.
|
|
||||||
|
|
||||||
Example usage:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# applying a single patch
|
|
||||||
$ pyenv install --patch 2.7.10 < /path/to/python.patch
|
|
||||||
|
|
||||||
# applying a patch from HTTP
|
|
||||||
$ pyenv install --patch 2.7.10 < <(curl -sSL http://git.io/python.patch)
|
|
||||||
|
|
||||||
# applying multiple patches
|
|
||||||
$ cat fix1.patch fix2.patch | pyenv install --patch 2.7.10
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Building with `--enable-shared`
|
|
||||||
|
|
||||||
You can build CPython with `--enable-shared` to install a version with
|
|
||||||
shared object.
|
|
||||||
|
|
||||||
If `--enable-shared` was found in `PYTHON_CONFIGURE_OPTS` or `CONFIGURE_OPTS`,
|
|
||||||
`python-build` will automatically set `RPATH` to the pyenv's prefix directory.
|
|
||||||
This means you don't have to set `LD_LIBRARY_PATH` or `DYLD_LIBRARY_PATH` for
|
|
||||||
the version(s) installed with `--enable-shared`.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 2.7.9
|
|
||||||
```
|
|
||||||
|
|
||||||
### Building for maximum performance
|
|
||||||
|
|
||||||
Building CPython with `--enable-optimizations` will result in a faster
|
|
||||||
interpreter at the cost of significantly longer build times. Most notably, this
|
|
||||||
enables PGO (profile guided optimization). While your mileage may vary, it is
|
|
||||||
common for performance improvement from this to be in the ballpark of 30%.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
env PYTHON_CONFIGURE_OPTS='--enable-optimizations --with-lto' PYTHON_CFLAGS='-march=native -mtune=native' pyenv install 3.6.0
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also customize the task used for profile guided optimization by setting
|
|
||||||
the `PROFILE_TASK` environment variable, for instance, `PROFILE_TASK='-m
|
|
||||||
test.regrtest --pgo -j0'` will run much faster than the default task.
|
|
||||||
|
|
||||||
### Checksum verification
|
|
||||||
|
|
||||||
If you have the `shasum`, `openssl`, or `sha256sum` tool installed, python-build will
|
|
||||||
automatically verify the SHA2 checksum of each downloaded package before
|
|
||||||
installing it.
|
|
||||||
|
|
||||||
Checksums are optional and specified as anchors on the package URL in each
|
|
||||||
definition. (All bundled definitions include checksums.)
|
|
||||||
|
|
||||||
### Package download mirrors
|
|
||||||
|
|
||||||
python-build will first attempt to download package files from a mirror hosted on
|
|
||||||
GitHub Pages. If a package is not available on the mirror, if the mirror
|
|
||||||
is down, or if the download is corrupt, python-build will fall back to the
|
|
||||||
official URL specified in the definition file.
|
|
||||||
|
|
||||||
You can point python-build to another mirror by specifying the
|
|
||||||
`PYTHON_BUILD_MIRROR_URL` environment variable--useful if you'd like to run your
|
|
||||||
own local mirror, for example. Package mirror URLs are constructed by joining
|
|
||||||
this variable with the SHA2 checksum of the package file.
|
|
||||||
|
|
||||||
If the mirror being used does not have the same checksum (*e.g.* with a
|
|
||||||
pull-through cache like Artifactory), you can set the
|
|
||||||
`PYTHON_BUILD_MIRROR_URL_SKIP_CHECKSUM` environment variable.
|
|
||||||
|
|
||||||
If you don't have an SHA2 program installed, python-build will skip the download
|
|
||||||
mirror and use official URLs instead. You can force python-build to bypass the
|
|
||||||
mirror by setting the `PYTHON_BUILD_SKIP_MIRROR` environment variable.
|
|
||||||
|
|
||||||
The official python-build download mirror is provided by
|
|
||||||
[GitHub Pages](http://yyuu.github.io/pythons/).
|
|
||||||
|
|
||||||
### Package download caching
|
|
||||||
|
|
||||||
You can instruct python-build to keep a local cache of downloaded package files
|
|
||||||
by setting the `PYTHON_BUILD_CACHE_PATH` environment variable. When set, package
|
|
||||||
files will be kept in this directory after the first successful download and
|
|
||||||
reused by subsequent invocations of `python-build` and `pyenv install`.
|
|
||||||
|
|
||||||
The `pyenv install` command defaults this path to `~/.pyenv/cache`, so in most
|
|
||||||
cases you can enable download caching simply by creating that directory.
|
|
||||||
|
|
||||||
### Keeping the build directory after installation
|
|
||||||
|
|
||||||
Both `python-build` and `pyenv install` accept the `-k` or `--keep` flag, which
|
|
||||||
tells python-build to keep the downloaded source after installation. This can be
|
|
||||||
useful if you need to use `gdb` and `memprof` with Python.
|
|
||||||
|
|
||||||
Source code will be kept in a parallel directory tree `~/.pyenv/sources` when
|
|
||||||
using `--keep` with the `pyenv install` command. You should specify the
|
|
||||||
location of the source code with the `PYTHON_BUILD_BUILD_PATH` environment
|
|
||||||
variable when using `--keep` with `python-build`.
|
|
||||||
|
|
||||||
|
|
||||||
## Getting Help
|
|
||||||
|
|
||||||
Please see the [pyenv wiki](https://github.com/pyenv/pyenv/wiki) for solutions to common problems.
|
|
||||||
|
|
||||||
[wiki]: https://github.com/pyenv/pyenv/wiki
|
|
||||||
|
|
||||||
If you can't find an answer on the wiki, open an issue on the [issue
|
|
||||||
tracker](https://github.com/pyenv/pyenv/issues). Be sure to include
|
|
||||||
the full build log for build failures.
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
### Testing new python versions
|
|
||||||
|
|
||||||
If you are contributing a new python version for python-build,
|
|
||||||
you can test the build in a [docker](https://www.docker.com/) container based on Ubuntu 18.04.
|
|
||||||
|
|
||||||
With docker installed:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker build -t my_container .
|
|
||||||
docker run my_container pyenv install <my_version>
|
|
||||||
```
|
|
||||||
|
|
||||||
To enter a shell which will allow you to build and then test a python version,
|
|
||||||
replace the second line with
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker run -it my_container
|
|
||||||
```
|
|
||||||
|
|
||||||
The container will need to be rebuilt whenever you change the repo,
|
|
||||||
but after the first build, this will be very fast,
|
|
||||||
as the layer including the build dependencies will be cached.
|
|
||||||
|
|
||||||
Changes made inside the container will not be persisted.
|
|
||||||
|
|
||||||
To test *all* new versions since a particular revision (e.g. `master`), `cd` to the root of your `pyenv` repo, and run this script:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
set -e
|
|
||||||
set -x
|
|
||||||
|
|
||||||
docker build -t pyenv-test-container .
|
|
||||||
|
|
||||||
git diff --name-only master \
|
|
||||||
| grep '^plugins/python-build/share/python-build/' \
|
|
||||||
| awk -F '/' '{print $NF}' \
|
|
||||||
| xargs -I _ docker run pyenv-test-container pyenv install _
|
|
||||||
```
|
|
||||||
|
|
||||||
- Build the docker image with the **t**ag pyenv-test-container
|
|
||||||
- Look for the names files changed since revision `master`
|
|
||||||
- Filter out any which don't live where python-build keeps its build scripts
|
|
||||||
- Look only at the file name (i.e. the python version name)
|
|
||||||
- Run a new docker container for each, building that version
|
|
||||||
|
|
||||||
@@ -1,295 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Summary: Install a Python version using python-build
|
|
||||||
#
|
|
||||||
# Usage: pyenv install [-f] [-kvp] <version>...
|
|
||||||
# pyenv install [-f] [-kvp] <definition-file>
|
|
||||||
# pyenv install -l|--list
|
|
||||||
# pyenv install --version
|
|
||||||
#
|
|
||||||
# -l/--list List all available versions
|
|
||||||
# -f/--force Install even if the version appears to be installed already
|
|
||||||
# -s/--skip-existing Skip if the version appears to be installed already
|
|
||||||
#
|
|
||||||
# python-build options:
|
|
||||||
#
|
|
||||||
# -k/--keep Keep source tree in $PYENV_BUILD_ROOT after installation
|
|
||||||
# (defaults to $PYENV_ROOT/sources)
|
|
||||||
# -p/--patch Apply a patch from stdin before building
|
|
||||||
# -v/--verbose Verbose mode: print compilation status to stdout
|
|
||||||
# --version Show version of python-build
|
|
||||||
# -g/--debug Build a debug version
|
|
||||||
#
|
|
||||||
# For detailed information on installing Python versions with
|
|
||||||
# python-build, including a list of environment variables for adjusting
|
|
||||||
# compilation, see: https://github.com/pyenv/pyenv#readme
|
|
||||||
#
|
|
||||||
set -e
|
|
||||||
[ -n "$PYENV_DEBUG" ] && set -x
|
|
||||||
|
|
||||||
# Add `share/python-build/` directory from each pyenv plugin to the list of
|
|
||||||
# paths where build definitions are looked up.
|
|
||||||
shopt -s nullglob
|
|
||||||
for plugin_path in "$PYENV_ROOT"/plugins/*/share/python-build; do
|
|
||||||
PYTHON_BUILD_DEFINITIONS="${PYTHON_BUILD_DEFINITIONS}:${plugin_path}"
|
|
||||||
done
|
|
||||||
export PYTHON_BUILD_DEFINITIONS
|
|
||||||
shopt -u nullglob
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
echo --list
|
|
||||||
echo --force
|
|
||||||
echo --skip-existing
|
|
||||||
echo --keep
|
|
||||||
echo --patch
|
|
||||||
echo --verbose
|
|
||||||
echo --version
|
|
||||||
echo --debug
|
|
||||||
exec python-build --definitions
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Load shared library functions
|
|
||||||
eval "$(python-build --lib)"
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
pyenv-help install 2>/dev/null
|
|
||||||
[ -z "$1" ] || exit "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
definitions() {
|
|
||||||
local query="$1"
|
|
||||||
python-build --definitions | $(type -P ggrep grep | head -n1) -F "$query" || true
|
|
||||||
}
|
|
||||||
|
|
||||||
indent() {
|
|
||||||
sed 's/^/ /'
|
|
||||||
}
|
|
||||||
|
|
||||||
unset FORCE
|
|
||||||
unset SKIP_EXISTING
|
|
||||||
unset KEEP
|
|
||||||
unset VERBOSE
|
|
||||||
unset HAS_PATCH
|
|
||||||
unset DEBUG
|
|
||||||
|
|
||||||
[ -n "$PYENV_DEBUG" ] && VERBOSE="-v"
|
|
||||||
|
|
||||||
parse_options "$@"
|
|
||||||
for option in "${OPTIONS[@]}"; do
|
|
||||||
case "$option" in
|
|
||||||
"h" | "help" )
|
|
||||||
usage 0
|
|
||||||
;;
|
|
||||||
"l" | "list" )
|
|
||||||
echo "Available versions:"
|
|
||||||
definitions | indent
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
"f" | "force" )
|
|
||||||
FORCE=true
|
|
||||||
;;
|
|
||||||
"s" | "skip-existing" )
|
|
||||||
SKIP_EXISTING=true
|
|
||||||
;;
|
|
||||||
"k" | "keep" )
|
|
||||||
[ -n "${PYENV_BUILD_ROOT}" ] || PYENV_BUILD_ROOT="${PYENV_ROOT}/sources"
|
|
||||||
;;
|
|
||||||
"v" | "verbose" )
|
|
||||||
VERBOSE="-v"
|
|
||||||
;;
|
|
||||||
"p" | "patch" )
|
|
||||||
HAS_PATCH="-p"
|
|
||||||
;;
|
|
||||||
"g" | "debug" )
|
|
||||||
DEBUG="-g"
|
|
||||||
;;
|
|
||||||
"version" )
|
|
||||||
exec python-build --version
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
usage 1 >&2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
unset VERSION_NAME
|
|
||||||
|
|
||||||
# The first argument contains the definition to install. If the
|
|
||||||
# argument is missing, try to install whatever local app-specific
|
|
||||||
# version is specified by pyenv. Show usage instructions if a local
|
|
||||||
# version is not specified.
|
|
||||||
DEFINITIONS=("${ARGUMENTS[@]}")
|
|
||||||
[[ "${#DEFINITIONS[*]}" -eq 0 ]] && DEFINITIONS=($(pyenv-local 2>/dev/null || true))
|
|
||||||
[[ "${#DEFINITIONS[*]}" -eq 0 ]] && usage 1 >&2
|
|
||||||
|
|
||||||
# Define `before_install` and `after_install` functions that allow
|
|
||||||
# plugin hooks to register a string of code for execution before or
|
|
||||||
# after the installation process.
|
|
||||||
declare -a before_hooks after_hooks
|
|
||||||
|
|
||||||
before_install() {
|
|
||||||
local hook="$1"
|
|
||||||
before_hooks["${#before_hooks[@]}"]="$hook"
|
|
||||||
}
|
|
||||||
|
|
||||||
after_install() {
|
|
||||||
local hook="$1"
|
|
||||||
after_hooks["${#after_hooks[@]}"]="$hook"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Plan cleanup on unsuccessful installation.
|
|
||||||
cleanup() {
|
|
||||||
[ -z "${PREFIX_EXISTS}" ] && rm -rf "$PREFIX"
|
|
||||||
}
|
|
||||||
|
|
||||||
trap cleanup SIGINT
|
|
||||||
|
|
||||||
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=$'\n' scripts=(`pyenv-hooks install`)
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
for script in "${scripts[@]}"; do source "$script"; done
|
|
||||||
|
|
||||||
COMBINED_STATUS=0
|
|
||||||
for DEFINITION in "${DEFINITIONS[@]}"; do
|
|
||||||
STATUS=0
|
|
||||||
|
|
||||||
# Try to resolve a prefix if user indeed gave a prefix.
|
|
||||||
# We install the version under the resolved name
|
|
||||||
# and hooks also see the resolved name
|
|
||||||
DEFINITION="$(pyenv-latest -q -k "$DEFINITION" || echo "$DEFINITION")"
|
|
||||||
|
|
||||||
# Set VERSION_NAME from $DEFINITION. Then compute the installation prefix.
|
|
||||||
VERSION_NAME="${DEFINITION##*/}"
|
|
||||||
[ -n "$DEBUG" ] && VERSION_NAME="${VERSION_NAME}-debug"
|
|
||||||
PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
|
|
||||||
|
|
||||||
[ -d "${PREFIX}" ] && PREFIX_EXISTS=1
|
|
||||||
|
|
||||||
# If the installation prefix exists, prompt for confirmation unless
|
|
||||||
# the --force option was specified.
|
|
||||||
if [ -d "${PREFIX}/bin" ]; then
|
|
||||||
if [ -z "$FORCE" ] && [ -z "$SKIP_EXISTING" ]; then
|
|
||||||
echo "pyenv: $PREFIX already exists" >&2
|
|
||||||
read -p "continue with installation? (y/N) "
|
|
||||||
|
|
||||||
case "$REPLY" in
|
|
||||||
y | Y | yes | YES ) ;;
|
|
||||||
* ) { STATUS=1; [[ $STATUS -gt $COMBINED_STATUS ]] && COMBINED_STATUS=$STATUS; }; continue ;;
|
|
||||||
esac
|
|
||||||
elif [ -n "$SKIP_EXISTING" ]; then
|
|
||||||
# Since we know the python version is already installed, and are opting to
|
|
||||||
# not force installation of existing versions, we just `exit 0` here to
|
|
||||||
# leave things happy
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If PYENV_BUILD_ROOT is set, always pass keep options to python-build.
|
|
||||||
if [ -n "${PYENV_BUILD_ROOT}" ]; then
|
|
||||||
export PYTHON_BUILD_BUILD_PATH="${PYENV_BUILD_ROOT}/${VERSION_NAME}"
|
|
||||||
KEEP="-k"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Set PYTHON_BUILD_CACHE_PATH to $PYENV_ROOT/cache, if the directory
|
|
||||||
# exists and the variable is not already set.
|
|
||||||
if [ -z "${PYTHON_BUILD_CACHE_PATH}" ] && [ -d "${PYENV_ROOT}/cache" ]; then
|
|
||||||
export PYTHON_BUILD_CACHE_PATH="${PYENV_ROOT}/cache"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${PYENV_BOOTSTRAP_VERSION}" ]; then
|
|
||||||
case "${VERSION_NAME}" in
|
|
||||||
[23]"."* )
|
|
||||||
# Default PYENV_VERSION to the friendly Python version. (The
|
|
||||||
# CPython installer requires an existing Python installation to run. An
|
|
||||||
# unsatisfied local .python-version file can cause the installer to
|
|
||||||
# fail.)
|
|
||||||
for version_info in "${VERSION_NAME%-dev}" "${VERSION_NAME%.*}" "${VERSION_NAME%%.*}"; do
|
|
||||||
# Anaconda's `curl` doesn't work on platform where `/etc/pki/tls/certs/ca-bundle.crt` isn't available (e.g. Debian)
|
|
||||||
for version in $(pyenv-whence "python${version_info}" 2>/dev/null || true); do
|
|
||||||
if [[ "${version}" != "anaconda"* ]] && [[ "${version}" != "miniconda"* ]]; then
|
|
||||||
PYENV_BOOTSTRAP_VERSION="${version}"
|
|
||||||
break 2
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
;;
|
|
||||||
"pypy"*"-dev" | "pypy"*"-src" )
|
|
||||||
# PyPy/PyPy3 requires existing Python 2.7 to build
|
|
||||||
if [ -n "${PYENV_RPYTHON_VERSION}" ]; then
|
|
||||||
PYENV_BOOTSTRAP_VERSION="${PYENV_RPYTHON_VERSION}"
|
|
||||||
else
|
|
||||||
for version in $(pyenv-versions --bare | sort -r); do
|
|
||||||
if [[ "${version}" == "2.7"* ]]; then
|
|
||||||
PYENV_BOOTSTRAP_VERSION="$version"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
if [ -n "$PYENV_BOOTSTRAP_VERSION" ]; then
|
|
||||||
for dep in pycparser; do
|
|
||||||
if ! PYENV_VERSION="$PYENV_BOOTSTRAP_VERSION" pyenv-exec python -c "import ${dep}" 1>/dev/null 2>&1; then
|
|
||||||
echo "pyenv-install: $VERSION_NAME: PyPy requires \`${dep}' in $PYENV_BOOTSTRAP_VERSION to build from source." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo "pyenv-install: $VERSION_NAME: PyPy requires Python 2.7 to build from source." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${PYENV_BOOTSTRAP_VERSION}" ]; then
|
|
||||||
export PYENV_VERSION="${PYENV_BOOTSTRAP_VERSION}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Execute `before_install` hooks.
|
|
||||||
for hook in "${before_hooks[@]}"; do eval "$hook"; done
|
|
||||||
|
|
||||||
# Invoke `python-build` and record the exit status in $STATUS.
|
|
||||||
python-build $KEEP $VERBOSE $HAS_PATCH $DEBUG "$DEFINITION" "$PREFIX" || \
|
|
||||||
{ STATUS=$?; [[ $STATUS -gt $COMBINED_STATUS ]] && COMBINED_STATUS=$STATUS; }
|
|
||||||
|
|
||||||
# Display a more helpful message if the definition wasn't found.
|
|
||||||
if [ "$STATUS" == "2" ]; then
|
|
||||||
{ candidates="$(definitions "$DEFINITION")"
|
|
||||||
here="$(dirname "${0%/*}")/../.."
|
|
||||||
if [ -n "$candidates" ]; then
|
|
||||||
echo
|
|
||||||
echo "The following versions contain \`$DEFINITION' in the name:"
|
|
||||||
echo "$candidates" | indent
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
echo "See all available versions with \`pyenv install --list'."
|
|
||||||
echo
|
|
||||||
echo -n "If the version you need is missing, try upgrading pyenv"
|
|
||||||
if [ "$here" != "${here#$(brew --prefix 2>/dev/null)}" ]; then
|
|
||||||
printf ":\n\n"
|
|
||||||
echo " brew update && brew upgrade pyenv"
|
|
||||||
elif [ -d "${here}/.git" ]; then
|
|
||||||
printf ":\n\n"
|
|
||||||
echo " cd ${here} && git pull && cd -"
|
|
||||||
else
|
|
||||||
printf ".\n"
|
|
||||||
fi
|
|
||||||
} >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Execute `after_install` hooks.
|
|
||||||
for hook in "${after_hooks[@]}"; do eval "$hook"; done
|
|
||||||
|
|
||||||
# Run `pyenv-rehash` after a successful installation.
|
|
||||||
if [[ $STATUS -eq 0 ]]; then
|
|
||||||
pyenv-rehash
|
|
||||||
else
|
|
||||||
cleanup
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
exit "${COMBINED_STATUS}"
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Summary: Uninstall Python versions
|
|
||||||
#
|
|
||||||
# Usage: pyenv uninstall [-f|--force] <version> ...
|
|
||||||
#
|
|
||||||
# -f Attempt to remove the specified version without prompting
|
|
||||||
# for confirmation. If the version does not exist, do not
|
|
||||||
# display an error message.
|
|
||||||
#
|
|
||||||
# See `pyenv versions` for a complete list of installed versions.
|
|
||||||
#
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Provide pyenv completions
|
|
||||||
if [ "$1" = "--complete" ]; then
|
|
||||||
echo --force
|
|
||||||
exec pyenv versions --bare
|
|
||||||
fi
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
pyenv-help uninstall 2>/dev/null
|
|
||||||
[ -z "$1" ] || exit "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
|
|
||||||
usage 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
unset FORCE
|
|
||||||
if [ "$1" = "-f" ] || [ "$1" = "--force" ]; then
|
|
||||||
FORCE=true
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
[ "$#" -gt 0 ] || usage 1 >&2
|
|
||||||
|
|
||||||
versions=("$@")
|
|
||||||
|
|
||||||
for version in "${versions[@]}"; do
|
|
||||||
case "$version" in
|
|
||||||
"" | -* )
|
|
||||||
usage 1 >&2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
declare -a before_hooks after_hooks
|
|
||||||
|
|
||||||
before_uninstall() {
|
|
||||||
local hook="$1"
|
|
||||||
before_hooks["${#before_hooks[@]}"]="$hook"
|
|
||||||
}
|
|
||||||
|
|
||||||
after_uninstall() {
|
|
||||||
local hook="$1"
|
|
||||||
after_hooks["${#after_hooks[@]}"]="$hook"
|
|
||||||
}
|
|
||||||
|
|
||||||
OLDIFS="$IFS"
|
|
||||||
IFS=$'\n' scripts=(`pyenv-hooks uninstall`)
|
|
||||||
IFS="$OLDIFS"
|
|
||||||
for script in "${scripts[@]}"; do source "$script"; done
|
|
||||||
|
|
||||||
uninstall-python() {
|
|
||||||
local DEFINITION="$1"
|
|
||||||
|
|
||||||
local VERSION_NAME="${DEFINITION##*/}"
|
|
||||||
local PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
|
|
||||||
|
|
||||||
if [ -z "$FORCE" ]; then
|
|
||||||
if [ ! -d "$PREFIX" ]; then
|
|
||||||
echo "pyenv: version \`$VERSION_NAME' not installed" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
read -p "pyenv: remove $PREFIX? [y|N] "
|
|
||||||
case "$REPLY" in
|
|
||||||
y | Y | yes | YES ) ;;
|
|
||||||
* ) exit 1 ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
for hook in "${before_hooks[@]}"; do eval "$hook"; done
|
|
||||||
|
|
||||||
if [ -d "$PREFIX" ]; then
|
|
||||||
rm -rf "$PREFIX"
|
|
||||||
pyenv-rehash
|
|
||||||
echo "pyenv: $VERSION_NAME uninstalled"
|
|
||||||
fi
|
|
||||||
|
|
||||||
for hook in "${after_hooks[@]}"; do eval "$hook"; done
|
|
||||||
}
|
|
||||||
|
|
||||||
for version in "${versions[@]}"; do
|
|
||||||
uninstall-python "$version"
|
|
||||||
done
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# Usage: PREFIX=/usr/local ./install.sh
|
|
||||||
#
|
|
||||||
# Installs python-build under $PREFIX.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
|
|
||||||
if [ -z "${PREFIX}" ]; then
|
|
||||||
PREFIX="/usr/local"
|
|
||||||
fi
|
|
||||||
|
|
||||||
BIN_PATH="${PREFIX}/bin"
|
|
||||||
SHARE_PATH="${PREFIX}/share/python-build"
|
|
||||||
|
|
||||||
mkdir -p "$BIN_PATH" "$SHARE_PATH"
|
|
||||||
|
|
||||||
install -p bin/* "$BIN_PATH"
|
|
||||||
for share in share/python-build/*; do
|
|
||||||
if [ -d "$share" ]; then
|
|
||||||
cp -RPp "$share" "$SHARE_PATH"
|
|
||||||
else
|
|
||||||
install -p -m 0644 "$share" "$SHARE_PATH"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# Scripts for updating python-build
|
|
||||||
|
|
||||||
Install dependencies with `pip install -r requirements.txt`.
|
|
||||||
|
|
||||||
## add_miniconda.py
|
|
||||||
|
|
||||||
```_add_miniconda
|
|
||||||
usage: add_miniconda.py [-h] [-d] [-v]
|
|
||||||
|
|
||||||
Script to add non-"latest" miniconda releases. Written for python 3.7. Checks
|
|
||||||
the miniconda download archives for new versions, then writes a build script
|
|
||||||
for any which do not exist locally, saving it to plugins/python-
|
|
||||||
build/share/python-build. Ignores releases below 4.3.30. Also ignores sub-
|
|
||||||
patch releases if that major.minor.patch already exists, but otherwise, takes
|
|
||||||
the latest sub-patch release for given OS/arch. Assumes all miniconda3
|
|
||||||
releases < 4.7 default to python 3.6, and anything else 3.7.
|
|
||||||
|
|
||||||
optional arguments:
|
|
||||||
-h, --help show this help message and exit
|
|
||||||
-d, --dry-run Do not write scripts, just report them to stdout
|
|
||||||
-v, --verbose Increase verbosity of logging
|
|
||||||
```
|
|
||||||
@@ -1,405 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Script to add non-"latest" miniconda releases.
|
|
||||||
Written for python 3.7.
|
|
||||||
|
|
||||||
Checks the miniconda download archives for new versions,
|
|
||||||
then writes a build script for any which do not exist locally,
|
|
||||||
saving it to plugins/python-build/share/python-build.
|
|
||||||
|
|
||||||
Ignores releases below 4.3.30.
|
|
||||||
Also ignores sub-patch releases if that major.minor.patch already exists,
|
|
||||||
but otherwise, takes the latest sub-patch release for given OS/arch.
|
|
||||||
Assumes all miniconda3 releases < 4.7 default to python 3.6, and anything else 3.7.
|
|
||||||
"""
|
|
||||||
import textwrap
|
|
||||||
from argparse import ArgumentParser
|
|
||||||
from collections import defaultdict
|
|
||||||
from enum import Enum
|
|
||||||
from functools import total_ordering
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import NamedTuple, List, Optional, DefaultDict, Dict
|
|
||||||
import logging
|
|
||||||
import string
|
|
||||||
|
|
||||||
import requests_html
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
CONDA_REPO = "https://repo.anaconda.com"
|
|
||||||
MINICONDA_REPO = CONDA_REPO + "/miniconda"
|
|
||||||
ANACONDA_REPO = CONDA_REPO + "/archive"
|
|
||||||
|
|
||||||
install_script_fmt = """
|
|
||||||
case "$(anaconda_architecture 2>/dev/null || true)" in
|
|
||||||
{install_lines}
|
|
||||||
* )
|
|
||||||
{{ echo
|
|
||||||
colorize 1 "ERROR"
|
|
||||||
echo ": The binary distribution of {tflavor} is not available for $(anaconda_architecture 2>/dev/null || true)."
|
|
||||||
echo
|
|
||||||
}} >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
""".lstrip()
|
|
||||||
|
|
||||||
install_line_fmt = """
|
|
||||||
"{os}-{arch}" )
|
|
||||||
install_script "{tflavor}{suffix}-{version_py_version}{version_str}-{os}-{arch}" "{repo}/{tflavor}{suffix}-{version_py_version}{version_str}-{os}-{arch}.sh#{md5}" "{flavor}" verify_{py_version}
|
|
||||||
;;
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
here = Path(__file__).resolve()
|
|
||||||
out_dir: Path = here.parent.parent / "share" / "python-build"
|
|
||||||
|
|
||||||
|
|
||||||
class StrEnum(str, Enum):
|
|
||||||
"""Enum subclass whose members are also instances of str
|
|
||||||
and directly comparable to strings. str type is forced at declaration.
|
|
||||||
|
|
||||||
Adapted from https://github.com/kissgyorgy/enum34-custom/blob/dbc89596761c970398701d26c6a5bbcfcf70f548/enum_custom.py#L100
|
|
||||||
(MIT license)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args):
|
|
||||||
for arg in args:
|
|
||||||
if not isinstance(arg, str):
|
|
||||||
raise TypeError("Not text %s:" % arg)
|
|
||||||
|
|
||||||
return super(StrEnum, cls).__new__(cls, *args)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str(self.value)
|
|
||||||
|
|
||||||
|
|
||||||
class SupportedOS(StrEnum):
|
|
||||||
LINUX = "Linux"
|
|
||||||
MACOSX = "MacOSX"
|
|
||||||
|
|
||||||
|
|
||||||
class SupportedArch(StrEnum):
|
|
||||||
AARCH64 = "aarch64"
|
|
||||||
ARM64 = "arm64"
|
|
||||||
PPC64LE = "ppc64le"
|
|
||||||
S390X = "s390x"
|
|
||||||
X86_64 = "x86_64"
|
|
||||||
X86 = "x86"
|
|
||||||
|
|
||||||
|
|
||||||
class Flavor(StrEnum):
|
|
||||||
ANACONDA = "anaconda"
|
|
||||||
MINICONDA = "miniconda"
|
|
||||||
|
|
||||||
|
|
||||||
class TFlavor(StrEnum):
|
|
||||||
ANACONDA = "Anaconda"
|
|
||||||
MINICONDA = "Miniconda"
|
|
||||||
|
|
||||||
|
|
||||||
class Suffix(StrEnum):
|
|
||||||
TWO = "2"
|
|
||||||
THREE = "3"
|
|
||||||
NONE = ""
|
|
||||||
|
|
||||||
|
|
||||||
class PyVersion(StrEnum):
|
|
||||||
PY27 = "py27"
|
|
||||||
PY36 = "py36"
|
|
||||||
PY37 = "py37"
|
|
||||||
PY38 = "py38"
|
|
||||||
PY39 = "py39"
|
|
||||||
PY310 = "py310"
|
|
||||||
PY311 = "py311"
|
|
||||||
|
|
||||||
def version(self):
|
|
||||||
first, *others = self.value[2:]
|
|
||||||
return f"{first}.{''.join(others)}"
|
|
||||||
|
|
||||||
def version_info(self):
|
|
||||||
return tuple(int(n) for n in self.version().split("."))
|
|
||||||
|
|
||||||
|
|
||||||
@total_ordering
|
|
||||||
class VersionStr(str):
|
|
||||||
def info(self):
|
|
||||||
return tuple(int(n) for n in self.replace("-", ".").split("."))
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return str(self) == str(other)
|
|
||||||
|
|
||||||
def __lt__(self, other):
|
|
||||||
if isinstance(other, VersionStr):
|
|
||||||
return self.info() < other.info()
|
|
||||||
raise ValueError("VersionStr can only be compared to other VersionStr")
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_info(cls, version_info):
|
|
||||||
return VersionStr(".".join(str(n) for n in version_info))
|
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
return hash(str(self))
|
|
||||||
|
|
||||||
|
|
||||||
class CondaVersion(NamedTuple):
|
|
||||||
flavor: Flavor
|
|
||||||
suffix: Suffix
|
|
||||||
version_str: VersionStr
|
|
||||||
py_version: Optional[PyVersion]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_str(cls, s):
|
|
||||||
"""
|
|
||||||
Convert a string of the form "miniconda_n-ver" or "miniconda_n-py_ver-ver" to a :class:`CondaVersion` object.
|
|
||||||
"""
|
|
||||||
miniconda_n, _, remainder = s.partition("-")
|
|
||||||
suffix = miniconda_n[-1]
|
|
||||||
if suffix in string.digits:
|
|
||||||
flavor = miniconda_n[:-1]
|
|
||||||
else:
|
|
||||||
flavor = miniconda_n
|
|
||||||
suffix = ""
|
|
||||||
|
|
||||||
components = remainder.split("-")
|
|
||||||
if flavor == Flavor.MINICONDA and len(components) >= 2:
|
|
||||||
py_ver, *ver_parts = components
|
|
||||||
py_ver = PyVersion(f"py{py_ver.replace('.', '')}")
|
|
||||||
ver = "-".join(ver_parts)
|
|
||||||
else:
|
|
||||||
ver = "-".join(components)
|
|
||||||
py_ver = None
|
|
||||||
|
|
||||||
return CondaVersion(Flavor(flavor), Suffix(suffix), VersionStr(ver), py_ver)
|
|
||||||
|
|
||||||
def to_filename(self):
|
|
||||||
if self.py_version:
|
|
||||||
return f"{self.flavor}{self.suffix}-{self.py_version.version()}-{self.version_str}"
|
|
||||||
else:
|
|
||||||
return f"{self.flavor}{self.suffix}-{self.version_str}"
|
|
||||||
|
|
||||||
def default_py_version(self):
|
|
||||||
"""
|
|
||||||
:class:`PyVersion` of Python used with this Miniconda version
|
|
||||||
"""
|
|
||||||
if self.py_version:
|
|
||||||
return self.py_version
|
|
||||||
elif self.suffix == Suffix.TWO:
|
|
||||||
return PyVersion.PY27
|
|
||||||
|
|
||||||
v = self.version_str.info()
|
|
||||||
if self.flavor == "miniconda":
|
|
||||||
# https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-python.html
|
|
||||||
if v < (4, 7):
|
|
||||||
return PyVersion.PY36
|
|
||||||
else:
|
|
||||||
return PyVersion.PY37
|
|
||||||
if self.flavor == "anaconda":
|
|
||||||
# https://docs.anaconda.com/free/anaconda/reference/release-notes/
|
|
||||||
if v >= (2023,7):
|
|
||||||
return PyVersion.PY311
|
|
||||||
if v >= (2023,3):
|
|
||||||
return PyVersion.PY310
|
|
||||||
if v >= (2021,11):
|
|
||||||
return PyVersion.PY39
|
|
||||||
if v >= (2020,7):
|
|
||||||
return PyVersion.PY38
|
|
||||||
if v >= (2020,2):
|
|
||||||
return PyVersion.PY37
|
|
||||||
if v >= (5,3,0):
|
|
||||||
return PyVersion.PY37
|
|
||||||
return PyVersion.PY36
|
|
||||||
|
|
||||||
raise ValueError(self.flavor)
|
|
||||||
|
|
||||||
|
|
||||||
class CondaSpec(NamedTuple):
|
|
||||||
tflavor: TFlavor
|
|
||||||
version: CondaVersion
|
|
||||||
os: SupportedOS
|
|
||||||
arch: SupportedArch
|
|
||||||
md5: str
|
|
||||||
repo: str
|
|
||||||
py_version: Optional[PyVersion] = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_filestem(cls, stem, md5, repo, py_version=None):
|
|
||||||
# The `*vers` captures the new trailing `-1` in some file names (a build number?)
|
|
||||||
# so they can be processed properly.
|
|
||||||
miniconda_n, *vers, os, arch = stem.split("-")
|
|
||||||
ver = "-".join(vers)
|
|
||||||
suffix = miniconda_n[-1]
|
|
||||||
if suffix in string.digits:
|
|
||||||
tflavor = miniconda_n[:-1]
|
|
||||||
else:
|
|
||||||
tflavor = miniconda_n
|
|
||||||
suffix = ""
|
|
||||||
flavor = tflavor.lower()
|
|
||||||
|
|
||||||
if ver.startswith("py"):
|
|
||||||
py_ver, ver = ver.split("_", maxsplit=1)
|
|
||||||
py_ver = PyVersion(py_ver)
|
|
||||||
else:
|
|
||||||
py_ver = None
|
|
||||||
spec = CondaSpec(
|
|
||||||
TFlavor(tflavor),
|
|
||||||
CondaVersion(Flavor(flavor), Suffix(suffix), VersionStr(ver), py_ver),
|
|
||||||
SupportedOS(os),
|
|
||||||
SupportedArch(arch),
|
|
||||||
md5,
|
|
||||||
repo,
|
|
||||||
)
|
|
||||||
if py_version is None:
|
|
||||||
spec = spec.with_py_version(spec.version.default_py_version())
|
|
||||||
return spec
|
|
||||||
|
|
||||||
def to_install_lines(self):
|
|
||||||
"""
|
|
||||||
Installation command for this version of Miniconda for use in a Pyenv installation script
|
|
||||||
"""
|
|
||||||
return install_line_fmt.format(
|
|
||||||
tflavor=self.tflavor,
|
|
||||||
flavor=self.version.flavor,
|
|
||||||
repo=self.repo,
|
|
||||||
suffix=self.version.suffix,
|
|
||||||
version_str=self.version.version_str,
|
|
||||||
version_py_version=f"{self.version.py_version}_" if self.version.py_version else "",
|
|
||||||
os=self.os,
|
|
||||||
arch=self.arch,
|
|
||||||
md5=self.md5,
|
|
||||||
py_version=self.py_version,
|
|
||||||
)
|
|
||||||
|
|
||||||
def with_py_version(self, py_version: PyVersion):
|
|
||||||
return CondaSpec(*self[:-1], py_version=py_version)
|
|
||||||
|
|
||||||
|
|
||||||
def make_script(specs: List[CondaSpec]):
|
|
||||||
install_lines = [s.to_install_lines() for s in specs]
|
|
||||||
return install_script_fmt.format(
|
|
||||||
install_lines="\n".join(install_lines),
|
|
||||||
tflavor=specs[0].tflavor,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_existing_condas(name):
|
|
||||||
"""
|
|
||||||
Enumerate existing Miniconda installation scripts in share/python-build/ except rolling releases.
|
|
||||||
|
|
||||||
:returns: A generator of :class:`CondaVersion` objects.
|
|
||||||
"""
|
|
||||||
logger.info("Getting known %(name)s versions",locals())
|
|
||||||
for p in out_dir.iterdir():
|
|
||||||
entry_name = p.name
|
|
||||||
if not p.is_file() or not entry_name.startswith(name):
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
v = CondaVersion.from_str(entry_name)
|
|
||||||
if v.version_str != "latest":
|
|
||||||
logger.debug("Found existing %(name)s version %(v)s", locals())
|
|
||||||
yield v
|
|
||||||
except ValueError:
|
|
||||||
logger.error("Unable to parse existing version %s", entry_name)
|
|
||||||
|
|
||||||
|
|
||||||
def get_available_condas(name, repo):
|
|
||||||
"""
|
|
||||||
Fetch remote miniconda versions.
|
|
||||||
|
|
||||||
:returns: A generator of :class:`CondaSpec` objects for each release available for download
|
|
||||||
except rolling releases.
|
|
||||||
"""
|
|
||||||
logger.info("Fetching remote %(name)s versions",locals())
|
|
||||||
session = requests_html.HTMLSession()
|
|
||||||
response = session.get(repo)
|
|
||||||
page: requests_html.HTML = response.html
|
|
||||||
table = page.find("table", first=True)
|
|
||||||
rows = table.find("tr")[1:]
|
|
||||||
for row in rows:
|
|
||||||
f, size, date, md5 = row.find("td")
|
|
||||||
fname = f.text
|
|
||||||
md5 = md5.text
|
|
||||||
|
|
||||||
if not fname.endswith(".sh"):
|
|
||||||
continue
|
|
||||||
stem = fname[:-3]
|
|
||||||
|
|
||||||
try:
|
|
||||||
s = CondaSpec.from_filestem(stem, md5, repo)
|
|
||||||
if s.version.version_str != "latest":
|
|
||||||
logger.debug("Found remote %(name)s version %(s)s", locals())
|
|
||||||
yield s
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def key_fn(spec: CondaSpec):
|
|
||||||
return (
|
|
||||||
spec.tflavor,
|
|
||||||
spec.version.version_str.info(),
|
|
||||||
spec.version.suffix.value,
|
|
||||||
spec.os.value,
|
|
||||||
spec.arch.value,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
parser = ArgumentParser(description=__doc__)
|
|
||||||
parser.add_argument(
|
|
||||||
"-d", "--dry-run", action="store_true",
|
|
||||||
help="Do not write scripts, just report them to stdout",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-v", "--verbose", action="count", default=0,
|
|
||||||
help="Increase verbosity of logging",
|
|
||||||
)
|
|
||||||
parsed = parser.parse_args()
|
|
||||||
|
|
||||||
log_level = {
|
|
||||||
0: logging.WARNING,
|
|
||||||
1: logging.INFO,
|
|
||||||
2: logging.DEBUG,
|
|
||||||
}.get(parsed.verbose, logging.DEBUG)
|
|
||||||
logging.basicConfig(level=log_level)
|
|
||||||
if parsed.verbose < 3:
|
|
||||||
logging.getLogger("requests").setLevel(logging.WARNING)
|
|
||||||
|
|
||||||
existing_versions = set()
|
|
||||||
available_specs = set()
|
|
||||||
for name,repo in ("miniconda",MINICONDA_REPO),("anaconda",ANACONDA_REPO):
|
|
||||||
existing_versions |= set(get_existing_condas(name))
|
|
||||||
available_specs |= set(get_available_condas(name, repo))
|
|
||||||
|
|
||||||
# version triple to triple-ified spec to raw spec
|
|
||||||
to_add: DefaultDict[
|
|
||||||
CondaVersion, Dict[CondaSpec, CondaSpec]
|
|
||||||
] = defaultdict(dict)
|
|
||||||
|
|
||||||
logger.info("Checking for new versions")
|
|
||||||
for s in sorted(available_specs, key=key_fn):
|
|
||||||
key = s.version
|
|
||||||
vv = key.version_str.info()
|
|
||||||
|
|
||||||
reason = None
|
|
||||||
if key in existing_versions:
|
|
||||||
reason = "already exists"
|
|
||||||
elif key.version_str.info() <= (4, 3, 30):
|
|
||||||
reason = "too old"
|
|
||||||
elif len(key.version_str.info()) >= 4 and "-" not in key.version_str:
|
|
||||||
reason = "ignoring hotfix releases"
|
|
||||||
|
|
||||||
if reason:
|
|
||||||
logger.debug("Ignoring version %(s)s (%(reason)s)", locals())
|
|
||||||
continue
|
|
||||||
|
|
||||||
to_add[key][s] = s
|
|
||||||
|
|
||||||
logger.info("Writing %s scripts", len(to_add))
|
|
||||||
for ver, d in to_add.items():
|
|
||||||
specs = list(d.values())
|
|
||||||
fpath = out_dir / ver.to_filename()
|
|
||||||
script_str = make_script(specs)
|
|
||||||
logger.info("Writing script for %s", ver)
|
|
||||||
if parsed.dry_run:
|
|
||||||
print(f"Would write spec to {fpath}:\n" + textwrap.indent(script_str, " "))
|
|
||||||
else:
|
|
||||||
with open(fpath, "w") as f:
|
|
||||||
f.write(script_str)
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
'Adds the latest miniforge and mambaforge releases.'
|
|
||||||
from pathlib import Path
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import string
|
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
logging.basicConfig(level=os.environ.get('LOGLEVEL', 'INFO'))
|
|
||||||
|
|
||||||
MINIFORGE_REPO = 'conda-forge/miniforge'
|
|
||||||
PYTHON_VERSION = '310'
|
|
||||||
DISTRIBUTIONS = ['miniforge', 'mambaforge']
|
|
||||||
|
|
||||||
install_script_fmt = """
|
|
||||||
case "$(anaconda_architecture 2>/dev/null || true)" in
|
|
||||||
{install_lines}
|
|
||||||
* )
|
|
||||||
{{ echo
|
|
||||||
colorize 1 "ERROR"
|
|
||||||
echo ": The binary distribution of {flavor} is not available for $(anaconda_architecture 2>/dev/null || true)."
|
|
||||||
echo
|
|
||||||
}} >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
""".lstrip()
|
|
||||||
|
|
||||||
install_line_fmt = """
|
|
||||||
"{os}-{arch}" )
|
|
||||||
install_script "{filename}" "{url}#{sha}" "miniconda" verify_py{py_version}
|
|
||||||
;;
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
here = Path(__file__).resolve()
|
|
||||||
out_dir: Path = here.parent.parent / "share" / "python-build"
|
|
||||||
|
|
||||||
def download_sha(url):
|
|
||||||
logger.debug('Downloading SHA file %(url)s', locals())
|
|
||||||
tup = tuple(reversed(requests.get(url).text.replace('./', '').rstrip().split()))
|
|
||||||
logger.debug('Got %(tup)s', locals())
|
|
||||||
return tup
|
|
||||||
|
|
||||||
def create_spec(filename, sha, url):
|
|
||||||
flavor_with_suffix, version, subversion, os, arch = filename.replace('.sh', '').split('-')
|
|
||||||
suffix = flavor_with_suffix[-1]
|
|
||||||
|
|
||||||
if suffix in string.digits:
|
|
||||||
flavor = flavor_with_suffix[:-1]
|
|
||||||
else:
|
|
||||||
flavor = flavor_with_suffix
|
|
||||||
|
|
||||||
spec = {
|
|
||||||
'filename': filename,
|
|
||||||
'sha': sha,
|
|
||||||
'url': url,
|
|
||||||
'py_version': PYTHON_VERSION,
|
|
||||||
'flavor': flavor,
|
|
||||||
'os': os,
|
|
||||||
'arch': arch,
|
|
||||||
'installer_filename': f'{flavor_with_suffix.lower()}-{version}-{subversion}',
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug('Created spec %(spec)s', locals())
|
|
||||||
|
|
||||||
return spec
|
|
||||||
|
|
||||||
def supported(filename):
|
|
||||||
return ('pypy' not in filename) and ('Windows' not in filename)
|
|
||||||
|
|
||||||
def add_version(release):
|
|
||||||
tag_name = release['tag_name']
|
|
||||||
download_urls = { f['name']: f['browser_download_url'] for f in release['assets'] }
|
|
||||||
shas = dict([download_sha(url) for (name, url) in download_urls.items() if name.endswith('.sha256') and tag_name in name])
|
|
||||||
specs = [create_spec(filename, sha, download_urls[filename]) for (filename, sha) in shas.items() if supported(filename)]
|
|
||||||
|
|
||||||
for distribution in DISTRIBUTIONS:
|
|
||||||
distribution_specs = [spec for spec in specs if distribution in spec['flavor'].lower()]
|
|
||||||
count = len(distribution_specs)
|
|
||||||
|
|
||||||
if count > 0:
|
|
||||||
output_file = out_dir / distribution_specs[0]['installer_filename']
|
|
||||||
|
|
||||||
logger.info('Writing %(count)d specs for %(distribution)s to %(output_file)s', locals())
|
|
||||||
|
|
||||||
script_str = install_script_fmt.format(
|
|
||||||
install_lines="\n".join([install_line_fmt.format_map(s) for s in distribution_specs]),
|
|
||||||
flavor=distribution_specs[0]['flavor'],
|
|
||||||
)
|
|
||||||
|
|
||||||
with open(output_file, 'w') as f:
|
|
||||||
f.write(script_str)
|
|
||||||
else:
|
|
||||||
logger.info('Did not find specs for %(distribution)s', locals())
|
|
||||||
|
|
||||||
for release in requests.get(f'https://api.github.com/repos/{MINIFORGE_REPO}/releases').json():
|
|
||||||
version = release['tag_name']
|
|
||||||
|
|
||||||
logger.info('Looking for %(version)s in %(out_dir)s', locals())
|
|
||||||
|
|
||||||
# This release has no mambaforge artifacts which causes the next check to always trigger.
|
|
||||||
# Build scripts for miniforge3-4.13.0-0 have already been generated.
|
|
||||||
# Assuming this was a fluke, we don't yet need to implement proactively checking all releases for contents
|
|
||||||
# or ignoring a release if _any_ of the flavors is already present in Pyenv.
|
|
||||||
if version == '4.13.0-0':
|
|
||||||
continue
|
|
||||||
|
|
||||||
if any(not list(out_dir.glob(f'{distribution}*-{version}')) for distribution in DISTRIBUTIONS):
|
|
||||||
logger.info('Downloading %(version)s', locals())
|
|
||||||
add_version(release)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
requests-html
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
require_gcc
|
|
||||||
install_package "readline-6.2" "https://ftpmirror.gnu.org/readline/readline-6.2.tar.gz#79a696070a058c233c72dd6ac697021cc64abd5ed51e59db867d66d196a89381" mac_readline --if has_broken_mac_readline
|
|
||||||
install_package "Python-2.1.3" "https://www.python.org/ftp/python/2.1.3/Python-2.1.3.tgz#1bcb5bb587948bc38f36db60e15c376009c56c66570e563a08a82bf7f227afb9" standard verify_py21
|
|
||||||
#install_package "setuptools-1.4.2" "https://pypi.python.org/packages/source/s/setuptools/setuptools-1.4.2.tar.gz#263986a60a83aba790a5bffc7d009ac88114ba4e908e5c90e453b3bf2155dbbd" python
|
|
||||||
#install_package "pip-1.1" "https://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz#993804bb947d18508acee02141281c77d27677f8c14eaa64d6287a1c53ef01c8" python
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
require_gcc
|
|
||||||
install_package "readline-6.2" "https://ftpmirror.gnu.org/readline/readline-6.2.tar.gz#79a696070a058c233c72dd6ac697021cc64abd5ed51e59db867d66d196a89381" mac_readline --if has_broken_mac_readline
|
|
||||||
install_package "Python-2.2.3" "https://www.python.org/ftp/python/2.2.3/Python-2.2.3.tgz#a8f92e6b89d47359fff0d1fbfe47f104afc77fd1cd5143e7332758b7bc100188" standard verify_py22
|
|
||||||
#install_package "setuptools-1.4.2" "https://pypi.python.org/packages/source/s/setuptools/setuptools-1.4.2.tar.gz#263986a60a83aba790a5bffc7d009ac88114ba4e908e5c90e453b3bf2155dbbd" python
|
|
||||||
#install_package "pip-1.1" "https://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz#993804bb947d18508acee02141281c77d27677f8c14eaa64d6287a1c53ef01c8" python
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
require_gcc
|
|
||||||
install_package "readline-6.2" "https://ftpmirror.gnu.org/readline/readline-6.2.tar.gz#79a696070a058c233c72dd6ac697021cc64abd5ed51e59db867d66d196a89381" mac_readline --if has_broken_mac_readline
|
|
||||||
install_package "Python-2.3.7" "https://www.python.org/ftp/python/2.3.7/Python-2.3.7.tgz#969a9891dce9f50b13e54f9890acaf2be66715a5895bf9b11111f320c205b90e" standard verify_py23
|
|
||||||
#install_package "setuptools-1.4.2" "https://pypi.python.org/packages/source/s/setuptools/setuptools-1.4.2.tar.gz#263986a60a83aba790a5bffc7d009ac88114ba4e908e5c90e453b3bf2155dbbd" python
|
|
||||||
#install_package "pip-1.1" "https://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz#993804bb947d18508acee02141281c77d27677f8c14eaa64d6287a1c53ef01c8" python
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
require_gcc
|
|
||||||
install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline --if has_broken_mac_readline
|
|
||||||
install_package "Python-2.4" "https://www.python.org/ftp/python/2.4/Python-2.4.tgz#ff746de0fae8691c082414b42a2bb172da8797e6e8ff66c9a39d2e452f7034e9" standard verify_py24
|
|
||||||
install_package "setuptools-1.4.2" "https://pypi.python.org/packages/source/s/setuptools/setuptools-1.4.2.tar.gz#263986a60a83aba790a5bffc7d009ac88114ba4e908e5c90e453b3bf2155dbbd" python
|
|
||||||
install_package "pip-1.1" "https://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz#993804bb947d18508acee02141281c77d27677f8c14eaa64d6287a1c53ef01c8" python
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
require_gcc
|
|
||||||
install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline --if has_broken_mac_readline
|
|
||||||
install_package "Python-2.4.1" "https://www.python.org/ftp/python/2.4.1/Python-2.4.1.tgz#f449c3b167389324c525ad99d02376c518ac11e163dbbbc13bc88a5c7101fd00" standard verify_py24
|
|
||||||
install_package "setuptools-1.4.2" "https://pypi.python.org/packages/source/s/setuptools/setuptools-1.4.2.tar.gz#263986a60a83aba790a5bffc7d009ac88114ba4e908e5c90e453b3bf2155dbbd" python
|
|
||||||
install_package "pip-1.1" "https://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz#993804bb947d18508acee02141281c77d27677f8c14eaa64d6287a1c53ef01c8" python
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
require_gcc
|
|
||||||
install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline --if has_broken_mac_readline
|
|
||||||
install_package "Python-2.4.2" "https://www.python.org/ftp/python/2.4.2/Python-2.4.2.tgz#2653e1846e87fd9b3ee287fefc965c80c54646548b4913a22265b0dd54493adf" standard verify_py24
|
|
||||||
install_package "setuptools-1.4.2" "https://pypi.python.org/packages/source/s/setuptools/setuptools-1.4.2.tar.gz#263986a60a83aba790a5bffc7d009ac88114ba4e908e5c90e453b3bf2155dbbd" python
|
|
||||||
install_package "pip-1.1" "https://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz#993804bb947d18508acee02141281c77d27677f8c14eaa64d6287a1c53ef01c8" python
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
require_gcc
|
|
||||||
install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline --if has_broken_mac_readline
|
|
||||||
install_package "Python-2.4.3" "https://www.python.org/ftp/python/2.4.3/Python-2.4.3.tgz#985a413932f5e31e6280b37da6b285a3a0b2748c6786643989ed9b23de97e2d5" standard verify_py24
|
|
||||||
install_package "setuptools-1.4.2" "https://pypi.python.org/packages/source/s/setuptools/setuptools-1.4.2.tar.gz#263986a60a83aba790a5bffc7d009ac88114ba4e908e5c90e453b3bf2155dbbd" python
|
|
||||||
install_package "pip-1.1" "https://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz#993804bb947d18508acee02141281c77d27677f8c14eaa64d6287a1c53ef01c8" python
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
require_gcc
|
|
||||||
install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline --if has_broken_mac_readline
|
|
||||||
install_package "Python-2.4.4" "https://www.python.org/ftp/python/2.4.4/Python-2.4.4.tgz#92be6e20cbc3111d9dd0c016d72ef7914c23b879dc52df7ba28df97afbf12e2e" standard verify_py24
|
|
||||||
install_package "setuptools-1.4.2" "https://pypi.python.org/packages/source/s/setuptools/setuptools-1.4.2.tar.gz#263986a60a83aba790a5bffc7d009ac88114ba4e908e5c90e453b3bf2155dbbd" python
|
|
||||||
install_package "pip-1.1" "https://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz#993804bb947d18508acee02141281c77d27677f8c14eaa64d6287a1c53ef01c8" python
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
require_gcc
|
|
||||||
install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline --if has_broken_mac_readline
|
|
||||||
install_package "Python-2.4.5" "https://www.python.org/ftp/python/2.4.5/Python-2.4.5.tgz#6ae6f67a388a7f70ed3a20eebab5aae995ee433089d1f1724095c62f4b7389a1" standard verify_py24
|
|
||||||
install_package "setuptools-1.4.2" "https://pypi.python.org/packages/source/s/setuptools/setuptools-1.4.2.tar.gz#263986a60a83aba790a5bffc7d009ac88114ba4e908e5c90e453b3bf2155dbbd" python
|
|
||||||
install_package "pip-1.1" "https://pypi.python.org/packages/source/p/pip/pip-1.1.tar.gz#993804bb947d18508acee02141281c77d27677f8c14eaa64d6287a1c53ef01c8" python
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user