Skip to content

Commit ca95284

Browse files
committed
Better descriptions in readme based on user conversations
1 parent 4d64d96 commit ca95284

3 files changed

Lines changed: 76 additions & 39 deletions

File tree

README.md

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,56 @@ to a uv-managed python consistent with your project’s `.python-version`
1010

1111
This project provides:
1212

13-
* `python` — a shim script that intercepts `python`/`python3.*` invocations
13+
- `python` — a shim script that intercepts `python`/`python3.*` invocations
1414
and resolves an appropriate interpreter using `uv python find`.
15-
* `install.bash` — an installer that copies the shim to `~/.local/uv-python-shims/`
15+
- `install.bash` — an installer that copies the shim to `~/.local/uv-python-shims/`
1616
and creates symlinks for `python3` and a set of `python3.X` names.
17-
* `tests/` — a lightweight bash test harness with mock `uv` + mock “python”
17+
- `tests/` — a lightweight bash test harness with mock `uv` + mock “python”
1818
executables.
1919

2020
References:
2121

22-
* `pyenv`
22+
- `pyenv`
2323
https://github.com/pyenv/pyenv
2424

25-
* `uv python find`
25+
- `uv python find`
2626
https://docs.astral.sh/uv/concepts/python-versions/#finding-a-python-executable
2727

2828

2929
## The main shim (`./python`)
3030

3131
**Requires:** `bash` and `uv` installed and on your `PATH`
3232

33-
* Runs `uv python find` to locate the best Python interpreter for the current
34-
working directory (uv walks upward looking for project metadata, including
35-
`.python-version`).
33+
The shim runs `uv python find` to locate the best Python interpreter for the current
34+
working directory:
35+
36+
* The find operation first looks for any python version constraints defined
37+
within a `.python-version` file or a project/workspace `pyproject.toml` file
38+
within the current directory or any parent directories.
3639

37-
* If the shim is invoked via a symlink with a versioned name like `python3.10`
38-
or `python3.14`, it enforces that **major.minor**:
40+
* It then searches the following locations **in order** until it finds the
41+
first available python that satisfies the version constraints (or the first
42+
one found if there are no constraints):
43+
1. Closest non-activated virtual environment (activated environments bypass
44+
the shim entirely so they are always selected with no version constraints).
45+
2. UV-managed python installations in order from newest to oldest versions.
46+
3. The first suitable python found on the `PATH`.
3947

40-
* It checks what `uv` would pick by default.
41-
* If the resolved interpreter does not match the requested `3.X`, it reruns
42-
`uv python find 3.X` and uses that interpreter instead.
48+
* If a suitable python is found, that python is executed via its absolute path.
49+
If a suitable python can NOT be found, the script will exit and display the
50+
error message given by uv.
4351

44-
* Avoids recursion:
52+
If the shim is invoked via a symlink with a versioned name like `python3.10`
53+
or `python3.14`, it enforces that **major.minor**. It does this by first checking
54+
what `uv` would pick by default and if the resolved interpreter does not match
55+
the requested `3.X`, it reruns `uv python find 3.X` and uses that interpreter instead.
4556

46-
* Removes the shim directory from `PATH` when invoking `uv` so `uv` won’t
47-
discover and re-run the shim as a candidate interpreter.
48-
* Executes the resolved interpreter via an absolute path.
57+
When invoking `uv` and executing the resolved python interpreter, the shim avoids
58+
recursion by removing the shim directory from `PATH`.
59+
60+
There are a number of possible configuration flags that can modify the behavior
61+
of `uv python find`. See the commented-out section near the top of the shim script
62+
and uncomment the flags desired to control python discovery.
4963

5064

5165
## Install main shim and symlinks
@@ -72,8 +86,8 @@ export PATH="$HOME/.local/uv-python-shims:$PATH"
7286

7387
Common locations:
7488

75-
* bash: `~/.bashrc` (and/or `~/.bash_profile`)
76-
* zsh: `~/.zshrc`
89+
- bash: `~/.bashrc` (and/or `~/.bash_profile`)
90+
- zsh: `~/.zshrc`
7791

7892
Then restart your shell, or run the export line once in your current session.
7993

@@ -86,12 +100,22 @@ python --version
86100
python3.11 --version
87101
```
88102

89-
If you have a `.python-version` in a directory, try running from inside it and
90-
from a subdirectory to confirm uv project discovery behaves as expected.
103+
If you have a `.python-version` in a directory, try running from inside that
104+
directory and from a subdirectory to confirm ***.python-version discovery***
105+
behaves as expected.
106+
107+
If you have a project or workspace defined with a `pyproject.toml` that includes
108+
a `requires-python` field, try running within that project directory or from a
109+
subdirectory to confirm ***project/workspace discovery*** behaves as expected.
110+
111+
If you have a non-activated virtual environment installed in a `.venv` subdirectory
112+
of a project, try running within the project directory or a subdirectory of that
113+
project to confirm ***virtual environment discovery*** behaves as expected.
114+
91115

92116
### Installer knobs
93117

94-
You can override the install destination or UI pacing:
118+
You can override the install destination or pacing:
95119

96120
```bash
97121
DEST_DIR="$HOME/.local/uv-python-shims" bash ./install.bash
@@ -112,9 +136,9 @@ The tests are written in bash and do **not** require a real `uv` install.
112136

113137
They work by:
114138

115-
* copying the shim under test into a temp directory
116-
* placing mock stubs on `PATH` (`tests/bin/uv`, plus fake interpreters)
117-
* asserting calls/behavior via logs and captured output
139+
- copying the shim under test into a temp directory
140+
- placing mock stubs on `PATH` (`tests/bin/uv`, plus fake interpreters)
141+
- asserting calls/behavior via logs and captured output
118142

119143
From the project root:
120144

@@ -162,14 +186,23 @@ python version switching to be less coupled from project management.
162186

163187
## Notes and caveats
164188

165-
* This shim delegates nearly all “what Python should I use?” logic to `uv`.
189+
- **Caution:** `uv-python-shim` should NOT be used as a solution for auto-activating
190+
a project's virtual environment. It's not suitable for that task. This shim will
191+
only auto-discover the environment's python interpreter and will not directly
192+
expose any other executables within that environment. Either manually activate
193+
using the mechanism recommended for your environment manager, or possibly auto-activate
194+
the environment with a solution like `direnv` or `mise`.
195+
196+
- This shim delegates nearly all “what Python should I use?” logic to `uv`.
166197
If `uv` changes discovery rules or output formats, the shim may need tweaks.
167198

168-
* The `python3.X` behavior is intentionally “major.minor enforcement” (not micro/patch).
199+
- The `python3.X` behavior is intentionally “major.minor enforcement” (not micro/patch).
169200

170-
* If you also want shims for other tools (`pip`, `pytest`, etc.), it should be
201+
- If you also want shims for other tools (`pip`, `pytest`, etc.), it should be
171202
straightforward to add siblings that run `"$resolved_python" -m pip ...` or similar.
172-
I don't need this so I didn't bother adding it.
203+
I don't need this so I didn't bother adding it. Also check the "Caution"
204+
note above. If you need more than just a python shim, you probably would do better
205+
with a different solution.
173206

174207
## License
175208

install.bash

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,12 @@ fi
7474

7575
info "Create main shim"
7676
run_step "Create directory ${DEST_DIR}" mkdir -p "${DEST_DIR}"
77-
78-
if command -v install >/dev/null 2>&1; then
79-
run_step "Copy shim to ${DEST_SHIM} (mode 0755)" install -m 0755 "${SRC_SHIM}" "${DEST_SHIM}"
80-
else
81-
warn "'install' not found; using cp + chmod"
82-
run_step "Copy shim to ${DEST_SHIM}" cp "${SRC_SHIM}" "${DEST_SHIM}"
83-
run_step "Set executable bit on ${DEST_SHIM}" chmod 0755 "${DEST_SHIM}"
84-
fi
85-
77+
run_step "Copy shim to ${DEST_SHIM}" cp "${SRC_SHIM}" "${DEST_SHIM}"
78+
run_step "Set executable bit on ${DEST_SHIM}" chmod 0755 "${DEST_SHIM}"
8679
printf "\n"
80+
8781
info "Create symlinks"
8882
run_step "Link ${DEST_DIR}/python3 -> python" ln -sfn "python" "${DEST_DIR}/python3"
89-
9083
for minor in ${MINOR_VERSIONS}; do
9184
run_step "Link ${DEST_DIR}/python3.${minor} -> python" ln -sfn "python" "${DEST_DIR}/python3.${minor}"
9285
done

python

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ set -euo pipefail
1414
py=""
1515
FLAGS=(--resolve-links)
1616

17+
# Uncomment to ignore virtual environments
18+
# Note that an 'activated' virtual environment will likely shadow this shim
19+
# so this flag is only useful for ignoring non-activated virtual environments.
20+
# FLAGS+=(--system)
21+
22+
# Uncomment to ignore '.python-version' files
23+
# FLAGS+=(--no-config)
24+
25+
# Uncomment to avoid discovering a project or workspace
26+
# FLAGS+=(--no-project)
27+
1728
# Uncomment to force uv-managed pythons only
1829
# FLAGS+=(--managed-python)
1930

0 commit comments

Comments
 (0)