Skip to content

Commit

Permalink
Encode free-threaded Python support in bridge model
Browse files Browse the repository at this point in the history
  • Loading branch information
messense committed Dec 25, 2024
1 parent 1afe25d commit 743b38c
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 3 deletions.
28 changes: 28 additions & 0 deletions src/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,23 @@ impl Bindings {
_ => MINIMUM_PYPY_MINOR,
}
}

/// free-threaded Python support
fn supports_free_threaded(&self) -> bool {
match self.name.as_str() {
"pyo3" | "pyo3-ffi" => {
let major_version = self.version.major;
let minor_version = self.version.minor;
// N.B. must check large minor versions first
if (major_version, minor_version) >= (0, 23) {
true
} else {
false
}
}
_ => false,
}
}
}

/// The way the rust code is used in the wheel
Expand Down Expand Up @@ -108,6 +125,17 @@ impl BridgeModel {
pub fn is_bin(&self) -> bool {
matches!(self, BridgeModel::Bin(_))
}

/// free-threaded Python support
pub fn supports_free_threaded(&self) -> bool {
match self {
BridgeModel::Bin(Some(bindings))
| BridgeModel::Bindings(bindings)
| BridgeModel::BindingsAbi3 { bindings, .. } => bindings.supports_free_threaded(),
BridgeModel::Bin(None) => true,
BridgeModel::Cffi | BridgeModel::UniFfi => false,
}
}
}

impl Display for BridgeModel {
Expand Down
41 changes: 38 additions & 3 deletions src/python_interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,9 @@ impl PythonInterpreter {
let min_pypy_minor = bindings
.map(|bindings| bindings.minimal_pypy_minor_version())
.unwrap_or(MINIMUM_PYPY_MINOR);
let supports_free_threaded = bridge
.map(|bridge| bridge.supports_free_threaded())
.unwrap_or(false);
InterpreterConfig::lookup_target(target)
.into_iter()
.filter_map(|config| match requires_python {
Expand Down Expand Up @@ -770,6 +773,13 @@ impl PythonInterpreter {
}
InterpreterKind::GraalPy => Some(config),
})
.filter_map(|config| {
if config.gil_disabled && !supports_free_threaded {
None
} else {
Some(config)
}
})
.collect()
}

Expand Down Expand Up @@ -1047,31 +1057,57 @@ mod tests {
"CPython 3.11",
"CPython 3.12",
"CPython 3.13",
"CPython 3.13t",
"PyPy 3.8",
"PyPy 3.9",
"PyPy 3.10",
]
"#]];
expected.assert_debug_eq(&pythons);

// pyo3 0.23+ should find CPython 3.13t
let pythons = PythonInterpreter::find_by_target(
&target,
Some(&VersionSpecifiers::from_str(">=3.8").unwrap()),
None,
Some(&BridgeModel::Bindings(Bindings {
name: "pyo3".to_string(),
version: semver::Version::new(0, 23, 0),
})),
)
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>();
let expected = expect![[r#"
[
"CPython 3.7m",
"CPython 3.8",
"CPython 3.9",
"CPython 3.10",
"CPython 3.11",
"CPython 3.12",
"CPython 3.13",
"CPython 3.13t",
"PyPy 3.9",
"PyPy 3.10",
]
"#]];
expected.assert_debug_eq(&pythons);

let pythons = PythonInterpreter::find_by_target(
&target,
Some(&VersionSpecifiers::from_str(">=3.8").unwrap()),
None,
)
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>();
let expected = expect![[r#"
[
"CPython 3.8",
"CPython 3.9",
"CPython 3.10",
"CPython 3.11",
"CPython 3.12",
"CPython 3.13",
"PyPy 3.8",
"PyPy 3.9",
"PyPy 3.10",
Expand All @@ -1093,7 +1129,6 @@ mod tests {
"CPython 3.11",
"CPython 3.12",
"CPython 3.13",
"CPython 3.13t",
"PyPy 3.10",
]
"#]];
Expand Down

0 comments on commit 743b38c

Please sign in to comment.