Skip to content

Commit

Permalink
docs: Update python documentation (#4260)
Browse files Browse the repository at this point in the history
- Update python documentation. 
- Indicate how one might use it with `uv` in the cookbook (at least
according to my understanding and after experimenting a bit with it)
- Re-order the sections in the python page with the section about `uv`,
`.python-version` and virtual env first
- Update the `mise` json schema to match the documentation (and observed
behavior)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
hverlin and autofix-ci[bot] authored Jan 29, 2025
1 parent a8ea4f3 commit 3156d3c
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 53 deletions.
2 changes: 1 addition & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ in mise and nvm. Here are some of the supported idiomatic version files:
| terraform | `.terraform-version`, `.packer-version`, `main.tf` |
| yarn | `.yarnrc` |

In mise these are enabled by default. You can disable them with [`mise settings idiomatic_version_file=false`](/configuration/settings.html#idiomatic_version_file) or for specific tools with [`mise settings idiomatic_version_file_disable_tools=['python']`](/configuration/settings.html#idiomatic_version_file_disable_tools).
In mise these are enabled by default. You can disable them with [`mise settings idiomatic_version_file false](/configuration/settings.html#idiomatic_version_file) or for specific tools with [`mise settings idiomatic_version_file_disable_tools python`](/configuration/settings.html#idiomatic_version_file_disable_tools).

There is a performance cost to having these when they're parsed as it's performed by the plugin in
`bin/parse-version-file`. However, these are [cached](/cache-behavior) so it's not a huge deal.
Expand Down
100 changes: 56 additions & 44 deletions docs/lang/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,42 @@ $ python3.11 -V
3.11.0
```

## Settings
See the [Python Cookbook](/mise-cookbook/python.html) for common tasks and examples.

`python-build` already has
a [handful of settings](https://github.com/pyenv/pyenv/tree/master/plugins/python-build), in
additional to that python in mise has a few extra configuration variables.
## `.python-version` support

Set these with `mise settings set [VARIABLE] [VALUE]` or by setting the environment variable.
`.python-version`/`.python-versions` files are supported by mise. See [idiomatic version files](/configuration.html#idiomatic-version-files).

<script setup>
import Settings from '/components/settings.vue';
</script>
<Settings child="python" :level="3" />
## Automatic virtualenv activation

Python comes with virtualenv support built in, use it with `mise.toml` configuration like
one of the following:

```toml
[tools]
python = "3.11" # [optional] will be used for the venv

[env]
_.python.venv = ".venv" # relative to this file's directory
_.python.venv = "/root/.venv" # can be absolute
_.python.venv = "{{env.HOME}}/.cache/venv/myproj" # can use templates
_.python.venv = { path = ".venv", create = true } # create the venv if it doesn't exist
_.python.venv = { path = ".venv", create = true, python = "3.10" } # use a specific python version
_.python.venv = { path = ".venv", create = true, python_create_args = ["--without-pip"] } # pass args to python -m venv
_.python.venv = { path = ".venv", create = true, uv_create_args = ["--system-site-packages"] } # pass args to uv venv
# Install seed packages (pip, setuptools, and wheel) into the virtual environment.
_.python.venv = { path = ".venv", create = true, uv_create_args = ['--seed'] }
```

The venv will need to be created manually with `python -m venv /path/to/venv` unless `create=true`.

## mise & uv

If you have installed `uv` (for example, with `mise use -g uv@latest`), `mise` will use it to create virtual environments. Otherwise, it will use the built-in `python -m venv` command.

Note that `uv` does not include `pip` by default (as `uv` provides `uv pip` instead). If you need the `pip` package, add the `uv_create_args = ['--seed']` option.

See the [mise + uv Cookbook](/mise-cookbook/python.html#mise-uv) for more examples.

## Default Python packages

Expand Down Expand Up @@ -84,6 +108,20 @@ its [dependencies](https://github.com/pyenv/pyenv/wiki#suggested-build-environme
before installing python with
python-build.

## Installing free-threaded python

Free-threaded python can be installed via python-build by running the following:

```bash
MISE_PYTHON_COMPILE=0 MISE_PYTHON_PRECOMPILED_FLAVOR=freethreaded+pgo-full mise install python
```

Or to compile with python-build:

```bash
MISE_PYTHON_COMPILE=1 PYTHON_BUILD_FREE_THREADING=1 mise install python
```

## Troubleshooting errors with Homebrew

If you normally use Homebrew and you see errors regarding OpenSSL,
Expand Down Expand Up @@ -122,41 +160,15 @@ CFLAGS="-I$(brew --prefix openssl)/include" \
brew link pkg-config
```

## Automatic virtualenv activation

Python comes with virtualenv support built in, use it with `mise.toml` configuration like
one of the following:

```toml
[tools]
python = "3.11" # [optional] will be used for the venv

[env]
_.python.venv = ".venv" # relative to this file's directory
_.python.venv = "/root/.venv" # can be absolute
_.python.venv = "{{env.HOME}}/.cache/venv/myproj" # can use templates
_.python.venv = { path = ".venv", create = true } # create the venv if it doesn't exist
_.python.venv = { path = ".venv", create = true, python = "3.10" } # use a specific python version
_.python.venv = { path = ".venv", create = true, python_create_args = ["--without-pip"] } # pass args to python -m venv
_.python.venv = { path = ".venv", create = true, uv_create_args = ["--system-site-packages"] } # pass args to uv venv
```

The venv will need to be created manually with `python -m venv /path/to/venv` unless `create=true`.

## Installing free-threaded python

Free-threaded python can be installed via python-build by running the following:

```bash
MISE_PYTHON_COMPILE=0 MISE_PYTHON_PRECOMPILED_FLAVOR=freethreaded+pgo-full mise install python
```

Or to compile with python-build:
## Settings

```bash
MISE_PYTHON_COMPILE=1 PYTHON_BUILD_FREE_THREADING=1 mise install python
```
`python-build` already has
a [handful of settings](https://github.com/pyenv/pyenv/tree/master/plugins/python-build), in
additional to that python in mise has a few extra configuration variables.

## `.python-version` support
Set these with `mise settings set [VARIABLE] [VALUE]` or by setting the environment variable.

`.python-version`/`.python-versions` files are supported by mise. See [idiomatic version files](/configuration.html#idiomatic-version-files).
<script setup>
import Settings from '/components/settings.vue';
</script>
<Settings child="python" :level="3" />
111 changes: 110 additions & 1 deletion docs/mise-cookbook/python.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Mise + Python Cookbook

Here are some tips on managing Python projects with mise.
Here are some tips on managing [Python](/lang/python.html) projects with mise.

## A Python Project with virtualenv

Expand Down Expand Up @@ -44,3 +44,112 @@ echo "Project: $PROJECT_NAME"
echo "Virtual Environment: $VIRTUAL_ENV"
'''
```

## mise + uv

If you are using a `uv` project initialized with `uv init .`, here is how you can use it with mise.

Here is how the `uv` project will look like:

```shell [uv-project]
.
├── .gitignore
├── .python-version
├── hello.py
├── pyproject.toml
└── README.md

cat .python-version
# 3.12
```

If you run `uv run hello.py` in the `uv` project, `uv` will automatically create a virtual environment for you using the python version specified in the `.python-version` file. This will also create a `uv.lock` file.

`mise` will detect the python version in `.python-version`, however, it won't use the virtual env created by `uv` by default. So, using `which python` will show a global python installation from `mise`.

```shell
mise i
which python
# ~/.local/share/mise/installs/python/3.12.4/bin/python
```

If you want `mise` to use the virtual environment created by `uv`, you can set the [`python.uv_venv_auto`](/lang/python.html#python.uv_venv_auto) setting to `true` in your `mise.toml` file.

```toml [mise.toml]
[settings]
python.uv_venv_auto = true
```

Using `which python` will now show the python version from the virtual environment created by `uv`.

```shell
which python
# ./uv-project/.venv/bin/python
```

Another option is to use `_.python.venv` in your `mise.toml` file to specify the path to the virtual environment created by `uv`.

```toml [mise.toml]
[env]
_.python.venv = { path = ".venv" }
```

### Syncing python versions installed by mise and uv

You can use [uv sync python --uv](/cli/sync/python.html#uv) to sync the python version installed by `mise` with the python version specified in the `.python-version` file in the `uv` project.

### uv scripts

You can take advantage of `uv run` in [`shebang`](/tasks/toml-tasks.html#shell-shebang) in toml or file tasks.
Note that using `--script` is required if the filename does not end in `.py`.

Here is an example toml task:

```toml [mise.toml]
[tools]
uv = 'latest'

[tasks.print_peps]
run = """
#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["requests<3", "rich"]
# ///
import requests
from rich.pretty import pprint
resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])
"""
```

Or as a file task:

```python [mise-tasks/print_peps.py]
#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["requests<3", "rich"]
# ///

import requests
from rich.pretty import pprint

resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])
```

You can then run it with `mise run print_peps`:

```shell
❯ mise run print_peps
[print_peps] $ ~/uv-project/mise-tasks/print_peps.py
Installed 9 packages in 8ms
[
│ ('1', 'PEP Purpose and Guidelines'),
│ ('2', 'Procedure for Adding New Modules'),
#...
]
```
11 changes: 11 additions & 0 deletions e2e/core/test_python_precompiled
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,14 @@
export MISE_PYTHON_COMPILE=0
assert_contains "mise use [email protected] 2>&1" "cpython-"
assert_contains "mise x -- python --version" "Python 3.12.3"

rm mise.toml
mise rm [email protected]

echo '3.12.3' >.python-version
assert_contains "mise i 2>&1" "mise [email protected]"
assert_contains "mise x -- python --version" "Python 3.12.3"

mise settings idiomatic_version_file_disable_tools python
mise use [email protected]
assert_contains "mise x -- python --version" "Python 3.13"
10 changes: 8 additions & 2 deletions schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,17 @@
},
"python_create_args": {
"description": "additional arguments to pass to python when creating a virtual environment",
"type": "string"
"type": "array",
"items": {
"type": "string"
}
},
"uv_create_args": {
"description": "additional arguments to pass to uv when creating a virtual environment",
"type": "string"
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["path"],
Expand Down
5 changes: 0 additions & 5 deletions src/config/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,6 @@ impl Settings {
if !settings.legacy_version_file {
settings.idiomatic_version_file = false;
}
if !settings.idiomatic_version_file_disable_tools.is_empty() {
settings
.disable_tools
.extend(settings.idiomatic_version_file_disable_tools.clone());
}
if settings.raw {
settings.jobs = 1;
}
Expand Down

0 comments on commit 3156d3c

Please sign in to comment.