Skip to content

Commit

Permalink
fix: detect gil (#2762)
Browse files Browse the repository at this point in the history
  • Loading branch information
nichmor authored Jan 3, 2025
1 parent 24ecf98 commit b85d993
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/pypi_modifiers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ miette = { workspace = true }
pixi_default_versions = { workspace = true }
pixi_manifest = { workspace = true }
rattler_conda_types = { workspace = true }
regex = { workspace = true }
uv-pep508 = { workspace = true }
uv-platform-tags = { workspace = true }
40 changes: 37 additions & 3 deletions crates/pypi_modifiers/src/pypi_tags.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use std::sync::OnceLock;

use miette::{Context, IntoDiagnostic};
use pixi_default_versions::{default_glibc_version, default_mac_os_version};
use pixi_manifest::{LibCSystemRequirement, SystemRequirements};
use rattler_conda_types::MatchSpec;
use rattler_conda_types::{Arch, PackageRecord, Platform};
use regex::Regex;
use uv_platform_tags::Os;
use uv_platform_tags::Tags;

Expand All @@ -25,7 +29,8 @@ pub fn get_pypi_tags(
let platform = get_platform_tags(platform, system_requirements)?;
let python_version = get_python_version(python_record)?;
let implementation_name = get_implementation_name(python_record)?;
create_tags(platform, python_version, implementation_name)
let gil_disabled = gil_disabled(python_record)?;
create_tags(platform, python_version, implementation_name, gil_disabled)
}

/// Create a uv platform tag for the specified platform
Expand Down Expand Up @@ -159,10 +164,40 @@ fn get_implementation_name(python_record: &PackageRecord) -> miette::Result<&'st
}
}

/// Return whether the specified record has gil disabled (by being a free-threaded python interpreter)
fn gil_disabled(python_record: &PackageRecord) -> miette::Result<bool> {
// In order to detect if the python interpreter is free-threaded, we look at the depends
// field of the record. If the record has a dependency on `python_abi`, then
// look at the build string to detect cpXXXt (free-threaded python interpreter).
static REGEX: OnceLock<Regex> = OnceLock::new();

let regex = REGEX.get_or_init(|| {
Regex::new(r"cp\d{3}t").expect("regex for free-threaded python interpreter should compile")
});

let deps = python_record
.depends
.iter()
.map(|dep| MatchSpec::from_str(dep, rattler_conda_types::ParseStrictness::Lenient))
.collect::<Result<Vec<MatchSpec>, _>>()
.into_diagnostic()?;

Ok(deps.iter().any(|spec| {
spec.name
.as_ref()
.is_some_and(|name| name.as_source() == "python_abi")
&& spec.build.as_ref().is_some_and(|build| {
let raw_str = format!("{}", build);
regex.is_match(&raw_str)
})
}))
}

fn create_tags(
platform: uv_platform_tags::Platform,
python_version: (u8, u8),
implementation_name: &str,
gil_disabled: bool,
) -> miette::Result<Tags> {
// Build the wheel tags based on the interpreter, the target platform, and the python version.
let tags = Tags::from_env(
Expand All @@ -172,8 +207,7 @@ fn create_tags(
// TODO: This might not be entirely correct..
python_version,
true,
// Should revisit this when this lands: https://github.com/conda-forge/python-feedstock/pull/679
false,
gil_disabled,
)
.into_diagnostic()
.context("failed to determine the python wheel tags for the target platform")?;
Expand Down
5 changes: 5 additions & 0 deletions docs/tutorials/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ xz 5.2.6 h57fd34a_0 230.2 KiB conda xz-5.2.6-h5
This is used to determine the Python version to install in the environment.
This way, pixi automatically manages/bootstraps the Python interpreter for you, so no more `brew`, `apt` or other system install steps.

!!! Free-threaded interpreters
If you want to use a free-threaded Python interpreter, you can add `python-freethreading = "*"` to the dependencies in your `pixi` configuration.
This ensures that a free-threaded version of Python is installed in the environment.
You can read more about free-threaded Python [here](https://docs.python.org/3/howto/free-threading-python.html).

Here, you can see the different conda and Pypi packages listed.
As you can see, the `pixi-py` package that we are working on is installed in editable mode.
Every environment in pixi is isolated but reuses files that are hard-linked from a central cache directory.
Expand Down

0 comments on commit b85d993

Please sign in to comment.