Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Update python documentation #4260

Merged
merged 10 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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).
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this right? I would think you'd need to use mise settings add|set

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, it works without add/set https://mise.jdx.dev/cli/settings.html#arguments. It's in the e2e test also now


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.
hverlin marked this conversation as resolved.
Show resolved Hide resolved

### 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