maturin 1.9.5__tar.gz → 1.9.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of maturin might be problematic. Click here for more details.
- {maturin-1.9.5 → maturin-1.9.6}/.pre-commit-config.yaml +2 -2
- {maturin-1.9.5 → maturin-1.9.6}/Cargo.lock +1 -1
- {maturin-1.9.5 → maturin-1.9.6}/Cargo.toml +1 -1
- {maturin-1.9.5 → maturin-1.9.6}/Changelog.md +7 -1
- {maturin-1.9.5 → maturin-1.9.6}/PKG-INFO +1 -1
- {maturin-1.9.5 → maturin-1.9.6}/src/build_options.rs +18 -2
- {maturin-1.9.5 → maturin-1.9.6}/src/python_interpreter/mod.rs +232 -306
- {maturin-1.9.5 → maturin-1.9.6}/.cirrus.yml +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/.codespellrc +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/.config/nextest.toml +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/.gitignore +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/MANIFEST.in +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/README.md +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/clippy.toml +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/license-apache +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/license-mit +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/maturin/__init__.py +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/maturin/__main__.py +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/maturin/bootstrap.py +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/maturin.schema.json +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/netlify.toml +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/pyproject.toml +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/setup.py +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/auditwheel/audit.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/auditwheel/manylinux-policy.json +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/auditwheel/mod.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/auditwheel/musllinux-policy.json +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/auditwheel/musllinux.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/auditwheel/patchelf.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/auditwheel/platform_tag.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/auditwheel/policy.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/auditwheel/repair.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/bridge.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/build_context.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/cargo_toml.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/ci.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/compile.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/compression.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/cross_compile.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/develop.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/generate_json_schema.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/lib.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/main.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/metadata.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/module_writer.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/new_project.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/project_layout.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/pyproject_toml.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/python_interpreter/config.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/python_interpreter/get_interpreter_metadata.py +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/source_distribution.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/target/legacy_py.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/target/mod.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/target/pypi_tags.rs +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/templates/.gitignore.j2 +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/templates/Cargo.toml.j2 +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/templates/__init__.py.j2 +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/templates/build.rs.j2 +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/templates/example.udl.j2 +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/templates/lib.rs.j2 +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/templates/main.rs.j2 +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/templates/pyproject.toml.j2 +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/templates/test_all.py.j2 +0 -0
- {maturin-1.9.5 → maturin-1.9.6}/src/upload.rs +0 -0
|
@@ -56,12 +56,12 @@ repos:
|
|
|
56
56
|
)
|
|
57
57
|
- id: mixed-line-ending
|
|
58
58
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
59
|
-
rev: v0.13.
|
|
59
|
+
rev: v0.13.3
|
|
60
60
|
hooks:
|
|
61
61
|
- id: ruff-format
|
|
62
62
|
- id: ruff
|
|
63
63
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
64
|
-
rev: v1.18.
|
|
64
|
+
rev: v1.18.2
|
|
65
65
|
hooks:
|
|
66
66
|
- id: mypy
|
|
67
67
|
entry: mypy maturin/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
authors = ["konstin <konstin@mailbox.org>", "messense <messense@icloud.com>"]
|
|
3
3
|
name = "maturin"
|
|
4
|
-
version = "1.9.
|
|
4
|
+
version = "1.9.6"
|
|
5
5
|
description = "Build and publish crates with pyo3, cffi and uniffi bindings as well as rust binaries as python packages"
|
|
6
6
|
exclude = [
|
|
7
7
|
"test-crates/**/*",
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.9.6]
|
|
4
|
+
|
|
5
|
+
* Fix regressions to interpreter platform detection on Windows from 1.9.5
|
|
6
|
+
* Further fixes to interpreter detection for Windows ARM64
|
|
7
|
+
|
|
3
8
|
## [1.9.5]
|
|
4
9
|
|
|
5
10
|
* Add builtin sysconfig for FreeBSD 14.2 amd64
|
|
@@ -1104,7 +1109,8 @@ points-0.1.0-py2.py3-none-manylinux1_x86_64.whl | 2,8M | 752K | 85K
|
|
|
1104
1109
|
|
|
1105
1110
|
* Initial Release
|
|
1106
1111
|
|
|
1107
|
-
[Unreleased]: https://github.com/pyo3/maturin/compare/v1.9.
|
|
1112
|
+
[Unreleased]: https://github.com/pyo3/maturin/compare/v1.9.6...HEAD
|
|
1113
|
+
[1.9.6]: https://github.com/pyo3/maturin/compare/v1.9.5...v1.9.6
|
|
1108
1114
|
[1.9.5]: https://github.com/pyo3/maturin/compare/v1.9.4...v1.9.5
|
|
1109
1115
|
[1.9.4]: https://github.com/pyo3/maturin/compare/v1.9.3...v1.9.4
|
|
1110
1116
|
[1.9.3]: https://github.com/pyo3/maturin/compare/v1.9.2...v1.9.3
|
|
@@ -374,8 +374,13 @@ impl BuildOptions {
|
|
|
374
374
|
}
|
|
375
375
|
}
|
|
376
376
|
} else {
|
|
377
|
-
interpreters =
|
|
378
|
-
|
|
377
|
+
interpreters = find_interpreter(
|
|
378
|
+
bridge,
|
|
379
|
+
interpreter,
|
|
380
|
+
target,
|
|
381
|
+
requires_python,
|
|
382
|
+
generate_import_lib,
|
|
383
|
+
)?;
|
|
379
384
|
}
|
|
380
385
|
|
|
381
386
|
let interpreters_str = interpreters
|
|
@@ -1288,6 +1293,7 @@ fn find_interpreter(
|
|
|
1288
1293
|
interpreter: &[PathBuf],
|
|
1289
1294
|
target: &Target,
|
|
1290
1295
|
requires_python: Option<&VersionSpecifiers>,
|
|
1296
|
+
generate_import_lib: bool,
|
|
1291
1297
|
) -> Result<Vec<PythonInterpreter>> {
|
|
1292
1298
|
let mut found_interpreters = Vec::new();
|
|
1293
1299
|
if !interpreter.is_empty() {
|
|
@@ -1301,6 +1307,16 @@ fn find_interpreter(
|
|
|
1301
1307
|
if !missing.is_empty() {
|
|
1302
1308
|
let sysconfig_interps =
|
|
1303
1309
|
find_interpreter_in_sysconfig(bridge, &missing, target, requires_python)?;
|
|
1310
|
+
|
|
1311
|
+
// Can only use sysconfig-derived interpreter on windows if generating the import lib
|
|
1312
|
+
if !sysconfig_interps.is_empty() && target.is_windows() && !generate_import_lib {
|
|
1313
|
+
let found = sysconfig_interps
|
|
1314
|
+
.iter()
|
|
1315
|
+
.map(|i| format!("{} {}.{}", i.interpreter_kind, i.major, i.minor))
|
|
1316
|
+
.collect::<Vec<_>>();
|
|
1317
|
+
bail!("Interpreters {found:?} were found in maturin's bundled sysconfig, but compiling for Windows without an interpreter requires PyO3's `generate-import-lib` feature");
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1304
1320
|
found_interpreters.extend(sysconfig_interps);
|
|
1305
1321
|
}
|
|
1306
1322
|
} else {
|
|
@@ -26,55 +26,6 @@ pub const MINIMUM_PYPY_MINOR: usize = 8;
|
|
|
26
26
|
pub const MAXIMUM_PYTHON_MINOR: usize = 13;
|
|
27
27
|
pub const MAXIMUM_PYPY_MINOR: usize = 11;
|
|
28
28
|
|
|
29
|
-
/// Identifies conditions where we do not want to build wheels
|
|
30
|
-
fn windows_interpreter_no_build(
|
|
31
|
-
major: usize,
|
|
32
|
-
minor: usize,
|
|
33
|
-
target: &Target,
|
|
34
|
-
platform: String,
|
|
35
|
-
min_python_minor: usize,
|
|
36
|
-
requires_python: Option<&VersionSpecifiers>,
|
|
37
|
-
) -> bool {
|
|
38
|
-
// Only python 3 with supported major versions
|
|
39
|
-
if major != 3 || minor < min_python_minor {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// From requires-python in pyproject.toml
|
|
44
|
-
if let Some(requires_python) = requires_python {
|
|
45
|
-
if !requires_python.contains(&Version::new([major as u64, minor as u64])) {
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
let python_arch = match platform.as_str() {
|
|
51
|
-
"win32" => Arch::X86,
|
|
52
|
-
"win-amd64" => Arch::X86_64,
|
|
53
|
-
"win-arm64" => Arch::Aarch64,
|
|
54
|
-
_ => {
|
|
55
|
-
eprintln!("⚠️ Warning: {major}.{minor} reports unknown platform '{platform}'. This may fail to build.");
|
|
56
|
-
// false => build it anyway
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
let target_arch = target.target_arch();
|
|
62
|
-
|
|
63
|
-
if python_arch != target.target_arch() {
|
|
64
|
-
eprintln!(
|
|
65
|
-
"👽 {major}.{minor} reports a platform '{platform}' (architecture '{python_arch}'), while the Rust target is '{target_arch}'. Skipping."
|
|
66
|
-
);
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
false
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
struct WindowsPythonInfo {
|
|
73
|
-
major: usize,
|
|
74
|
-
minor: usize,
|
|
75
|
-
platform: String, // e.g. win32, win-amd64, win-arm64
|
|
76
|
-
}
|
|
77
|
-
|
|
78
29
|
/// On windows regular Python installs are supported along with environments
|
|
79
30
|
/// being managed by `conda`.
|
|
80
31
|
///
|
|
@@ -116,12 +67,32 @@ fn find_all_windows(
|
|
|
116
67
|
target: &Target,
|
|
117
68
|
bridge: &BridgeModel,
|
|
118
69
|
requires_python: Option<&VersionSpecifiers>,
|
|
119
|
-
) -> Result<Vec<
|
|
70
|
+
) -> Result<Vec<PythonInterpreter>> {
|
|
120
71
|
let min_python_minor = bridge.minimal_python_minor_version();
|
|
121
|
-
let code = "import sys; print(sys.executable or '')";
|
|
122
72
|
let mut interpreter = vec![];
|
|
123
73
|
let mut versions_found = HashSet::new();
|
|
124
74
|
|
|
75
|
+
macro_rules! maybe_add_interp {
|
|
76
|
+
($executable:expr) => {
|
|
77
|
+
PythonInterpreter::check_executable($executable, target, bridge).map(|interp| {
|
|
78
|
+
if let Some(interp) = interp {
|
|
79
|
+
let major = interp.major;
|
|
80
|
+
let minor = interp.minor;
|
|
81
|
+
if major == 3
|
|
82
|
+
&& minor >= min_python_minor
|
|
83
|
+
&& !versions_found.contains(&(major, minor))
|
|
84
|
+
&& requires_python.map_or(true, |requires_python| {
|
|
85
|
+
requires_python.contains(&Version::new([major as u64, minor as u64]))
|
|
86
|
+
})
|
|
87
|
+
{
|
|
88
|
+
interpreter.push(interp);
|
|
89
|
+
versions_found.insert((major, minor));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
125
96
|
// If Python is installed from Python.org it should include the "python launcher"
|
|
126
97
|
// which is used to find the installed interpreters
|
|
127
98
|
let execution = Command::new("cmd")
|
|
@@ -156,38 +127,7 @@ fn find_all_windows(
|
|
|
156
127
|
if !executable_path.exists() {
|
|
157
128
|
continue;
|
|
158
129
|
}
|
|
159
|
-
|
|
160
|
-
if windows_interpreter_no_build(
|
|
161
|
-
major,
|
|
162
|
-
minor,
|
|
163
|
-
target,
|
|
164
|
-
python_info.platform,
|
|
165
|
-
min_python_minor,
|
|
166
|
-
requires_python,
|
|
167
|
-
) {
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
let output = Command::new(executable).args(["-c", code]).output();
|
|
172
|
-
let output = match output {
|
|
173
|
-
Ok(output) => output,
|
|
174
|
-
Err(err) => {
|
|
175
|
-
eprintln!(
|
|
176
|
-
"⚠️ Warning: failed to determine the path to python for `{executable}`: {err}"
|
|
177
|
-
);
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
let path = str::from_utf8(&output.stdout).unwrap().trim();
|
|
182
|
-
if !output.status.success() || path.trim().is_empty() {
|
|
183
|
-
eprintln!(
|
|
184
|
-
"⚠️ Warning: couldn't determine the path to python for `{executable}`"
|
|
185
|
-
);
|
|
186
|
-
continue;
|
|
187
|
-
}
|
|
188
|
-
interpreter.push(path.to_string());
|
|
189
|
-
versions_found.insert((major, minor));
|
|
190
|
-
}
|
|
130
|
+
maybe_add_interp!(executable_path)?;
|
|
191
131
|
}
|
|
192
132
|
}
|
|
193
133
|
}
|
|
@@ -218,20 +158,7 @@ fn find_all_windows(
|
|
|
218
158
|
} else {
|
|
219
159
|
Path::new(&path).join("python")
|
|
220
160
|
};
|
|
221
|
-
|
|
222
|
-
if windows_interpreter_no_build(
|
|
223
|
-
python_info.major,
|
|
224
|
-
python_info.minor,
|
|
225
|
-
target,
|
|
226
|
-
python_info.platform,
|
|
227
|
-
min_python_minor,
|
|
228
|
-
requires_python,
|
|
229
|
-
) {
|
|
230
|
-
continue;
|
|
231
|
-
}
|
|
232
|
-
interpreter.push(String::from(executable.to_str().unwrap()));
|
|
233
|
-
versions_found.insert((python_info.major, python_info.minor));
|
|
234
|
-
}
|
|
161
|
+
maybe_add_interp!(executable.as_path())?;
|
|
235
162
|
}
|
|
236
163
|
}
|
|
237
164
|
|
|
@@ -239,20 +166,7 @@ fn find_all_windows(
|
|
|
239
166
|
for minor in min_python_minor..=bridge.maximum_python_minor_version() {
|
|
240
167
|
if !versions_found.contains(&(3, minor)) {
|
|
241
168
|
let executable = format!("python3.{minor}.exe");
|
|
242
|
-
|
|
243
|
-
if windows_interpreter_no_build(
|
|
244
|
-
python_info.major,
|
|
245
|
-
python_info.minor,
|
|
246
|
-
target,
|
|
247
|
-
python_info.platform,
|
|
248
|
-
min_python_minor,
|
|
249
|
-
requires_python,
|
|
250
|
-
) {
|
|
251
|
-
continue;
|
|
252
|
-
}
|
|
253
|
-
interpreter.push(executable);
|
|
254
|
-
versions_found.insert((3, minor));
|
|
255
|
-
}
|
|
169
|
+
maybe_add_interp!(Path::new(&executable))?;
|
|
256
170
|
}
|
|
257
171
|
}
|
|
258
172
|
|
|
@@ -264,49 +178,6 @@ fn find_all_windows(
|
|
|
264
178
|
Ok(interpreter)
|
|
265
179
|
}
|
|
266
180
|
|
|
267
|
-
fn windows_python_info(executable: &Path) -> Result<Option<WindowsPythonInfo>> {
|
|
268
|
-
let python_info = Command::new(executable)
|
|
269
|
-
.arg("-c")
|
|
270
|
-
.arg("import sys, sysconfig; print(sys.version_info.major, sys.version_info.minor, sysconfig.get_platform())")
|
|
271
|
-
.output();
|
|
272
|
-
|
|
273
|
-
let python_info = match python_info {
|
|
274
|
-
Ok(python_info) => python_info,
|
|
275
|
-
Err(err) => {
|
|
276
|
-
if err.kind() == io::ErrorKind::NotFound {
|
|
277
|
-
// python executable not found
|
|
278
|
-
return Ok(None);
|
|
279
|
-
} else {
|
|
280
|
-
bail!(
|
|
281
|
-
"Error getting Python version info from {}",
|
|
282
|
-
executable.display()
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
let version_info = str::from_utf8(&python_info.stdout).unwrap();
|
|
289
|
-
|
|
290
|
-
// Split into 3 segments: major, minor, platform by spaces
|
|
291
|
-
let segments: Vec<&str> = version_info.splitn(3, ' ').collect();
|
|
292
|
-
let [major, minor, platform] = segments.as_slice() else {
|
|
293
|
-
bail!(
|
|
294
|
-
"Unexpected output for Python version info from {}: '{}'",
|
|
295
|
-
executable.display(),
|
|
296
|
-
version_info
|
|
297
|
-
);
|
|
298
|
-
};
|
|
299
|
-
// can then parse each substring
|
|
300
|
-
let major = major.parse::<usize>().ok().unwrap_or(0);
|
|
301
|
-
let minor = minor.parse::<usize>().ok().unwrap_or(0);
|
|
302
|
-
|
|
303
|
-
Ok(Some(WindowsPythonInfo {
|
|
304
|
-
major,
|
|
305
|
-
minor,
|
|
306
|
-
platform: platform.to_string(),
|
|
307
|
-
}))
|
|
308
|
-
}
|
|
309
|
-
|
|
310
181
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Deserialize, clap::ValueEnum)]
|
|
311
182
|
#[serde(rename_all = "lowercase")]
|
|
312
183
|
#[clap(rename_all = "lower")]
|
|
@@ -644,9 +515,15 @@ impl PythonInterpreter {
|
|
|
644
515
|
let mut metadata_py = tempfile::NamedTempFile::new()?;
|
|
645
516
|
write!(metadata_py, "{GET_INTERPRETER_METADATA}")?;
|
|
646
517
|
let mut cmd = Command::new("cmd");
|
|
518
|
+
let suffix = match target.target_arch() {
|
|
519
|
+
Arch::X86 => "-32",
|
|
520
|
+
Arch::X86_64 => "-64",
|
|
521
|
+
Arch::Aarch64 => "-arm64",
|
|
522
|
+
_ => "",
|
|
523
|
+
};
|
|
647
524
|
cmd.arg("/c")
|
|
648
525
|
.arg("py")
|
|
649
|
-
.arg(format!("-{}
|
|
526
|
+
.arg(format!("-{ver}{suffix}"))
|
|
650
527
|
.arg(metadata_py.path())
|
|
651
528
|
.env("PYTHONNOUSERSITE", "1");
|
|
652
529
|
let output = cmd.output();
|
|
@@ -669,6 +546,18 @@ impl PythonInterpreter {
|
|
|
669
546
|
.context(err_msg)
|
|
670
547
|
.context(String::from_utf8_lossy(&output.stdout).trim().to_string())?;
|
|
671
548
|
|
|
549
|
+
Self::from_metadata_message(executable, target, bridge, message)
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/// Configure a `PythonInterpreter` from the metadata message.
|
|
553
|
+
///
|
|
554
|
+
/// Returns `None` if the interpreter is not suitable to use (e.g. too old or wrong architecture)
|
|
555
|
+
fn from_metadata_message(
|
|
556
|
+
executable: impl AsRef<Path>,
|
|
557
|
+
target: &Target,
|
|
558
|
+
bridge: &BridgeModel,
|
|
559
|
+
message: InterpreterMetadataMessage,
|
|
560
|
+
) -> Result<Option<PythonInterpreter>> {
|
|
672
561
|
if (message.major == 2 && message.minor != 7) || (message.major == 3 && message.minor < 5) {
|
|
673
562
|
debug!(
|
|
674
563
|
"Skipping outdated python interpreter '{}'",
|
|
@@ -691,6 +580,41 @@ impl PythonInterpreter {
|
|
|
691
580
|
executable.as_ref().display()
|
|
692
581
|
))?;
|
|
693
582
|
|
|
583
|
+
let executable = message
|
|
584
|
+
.executable
|
|
585
|
+
.map(PathBuf::from)
|
|
586
|
+
.unwrap_or_else(|| executable.as_ref().to_path_buf());
|
|
587
|
+
|
|
588
|
+
if target.is_windows() {
|
|
589
|
+
'windows_arch_check: {
|
|
590
|
+
// on windows we must check the architecture, because three different architectures
|
|
591
|
+
// can all run on the same hardware
|
|
592
|
+
let python_arch = match message.platform.as_str().trim() {
|
|
593
|
+
"win32" => Arch::X86,
|
|
594
|
+
"win-amd64" => Arch::X86_64,
|
|
595
|
+
"win-arm64" => Arch::Aarch64,
|
|
596
|
+
_ => {
|
|
597
|
+
eprintln!(
|
|
598
|
+
"⚠️ Warning: '{}' reports unknown platform. This may fail to build.",
|
|
599
|
+
executable.display()
|
|
600
|
+
);
|
|
601
|
+
break 'windows_arch_check;
|
|
602
|
+
}
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
if python_arch != target.target_arch() {
|
|
606
|
+
eprintln!(
|
|
607
|
+
"👽 '{}' reports a platform '{platform}' (architecture '{python_arch}'), while the Rust target is '{target_arch}'. Skipping.",
|
|
608
|
+
executable.display(),
|
|
609
|
+
platform = message.platform,
|
|
610
|
+
python_arch = python_arch,
|
|
611
|
+
target_arch = target.target_arch(),
|
|
612
|
+
);
|
|
613
|
+
return Ok(None);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
694
618
|
let platform = if message.platform.starts_with("macosx") {
|
|
695
619
|
// We don't use platform from sysconfig on macOS
|
|
696
620
|
None
|
|
@@ -698,10 +622,6 @@ impl PythonInterpreter {
|
|
|
698
622
|
Some(message.platform.to_lowercase().replace(['-', '.'], "_"))
|
|
699
623
|
};
|
|
700
624
|
|
|
701
|
-
let executable = message
|
|
702
|
-
.executable
|
|
703
|
-
.map(PathBuf::from)
|
|
704
|
-
.unwrap_or_else(|| executable.as_ref().to_path_buf());
|
|
705
625
|
debug!(
|
|
706
626
|
"Found {} interpreter at {}",
|
|
707
627
|
interpreter,
|
|
@@ -807,37 +727,38 @@ impl PythonInterpreter {
|
|
|
807
727
|
bridge: &BridgeModel,
|
|
808
728
|
requires_python: Option<&VersionSpecifiers>,
|
|
809
729
|
) -> Result<Vec<PythonInterpreter>> {
|
|
810
|
-
|
|
730
|
+
if target.is_windows() {
|
|
811
731
|
// TOFIX: add PyPy support to Windows
|
|
812
|
-
find_all_windows(target, bridge, requires_python)
|
|
813
|
-
} else {
|
|
814
|
-
let mut executables: Vec<String> = (bridge.minimal_python_minor_version()
|
|
815
|
-
..=bridge.maximum_python_minor_version())
|
|
816
|
-
.filter(|minor| {
|
|
817
|
-
requires_python
|
|
818
|
-
.map(|requires_python| {
|
|
819
|
-
requires_python.contains(&Version::new([3, *minor as u64]))
|
|
820
|
-
})
|
|
821
|
-
.unwrap_or(true)
|
|
822
|
-
})
|
|
823
|
-
.map(|minor| format!("python3.{minor}"))
|
|
824
|
-
.collect();
|
|
825
|
-
// Also try to find PyPy for cffi and pyo3 bindings
|
|
826
|
-
if *bridge == BridgeModel::Cffi || bridge.is_pyo3() {
|
|
827
|
-
executables.extend(
|
|
828
|
-
(bridge.minimal_pypy_minor_version()..=bridge.maximum_pypy_minor_version())
|
|
829
|
-
.filter(|minor| {
|
|
830
|
-
requires_python
|
|
831
|
-
.map(|requires_python| {
|
|
832
|
-
requires_python.contains(&Version::new([3, *minor as u64]))
|
|
833
|
-
})
|
|
834
|
-
.unwrap_or(true)
|
|
835
|
-
})
|
|
836
|
-
.map(|minor| format!("pypy3.{minor}")),
|
|
837
|
-
);
|
|
838
|
-
}
|
|
839
|
-
executables
|
|
732
|
+
return find_all_windows(target, bridge, requires_python);
|
|
840
733
|
};
|
|
734
|
+
|
|
735
|
+
let mut executables: Vec<String> = (bridge.minimal_python_minor_version()
|
|
736
|
+
..=bridge.maximum_python_minor_version())
|
|
737
|
+
.filter(|minor| {
|
|
738
|
+
requires_python
|
|
739
|
+
.map(|requires_python| {
|
|
740
|
+
requires_python.contains(&Version::new([3, *minor as u64]))
|
|
741
|
+
})
|
|
742
|
+
.unwrap_or(true)
|
|
743
|
+
})
|
|
744
|
+
.map(|minor| format!("python3.{minor}"))
|
|
745
|
+
.collect();
|
|
746
|
+
|
|
747
|
+
// Also try to find PyPy for cffi and pyo3 bindings
|
|
748
|
+
if *bridge == BridgeModel::Cffi || bridge.is_pyo3() {
|
|
749
|
+
executables.extend(
|
|
750
|
+
(bridge.minimal_pypy_minor_version()..=bridge.maximum_pypy_minor_version())
|
|
751
|
+
.filter(|minor| {
|
|
752
|
+
requires_python
|
|
753
|
+
.map(|requires_python| {
|
|
754
|
+
requires_python.contains(&Version::new([3, *minor as u64]))
|
|
755
|
+
})
|
|
756
|
+
.unwrap_or(true)
|
|
757
|
+
})
|
|
758
|
+
.map(|minor| format!("pypy3.{minor}")),
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
|
|
841
762
|
let mut available_versions = Vec::new();
|
|
842
763
|
for executable in executables {
|
|
843
764
|
if let Some(version) = PythonInterpreter::check_executable(executable, target, bridge)?
|
|
@@ -1195,135 +1116,140 @@ mod tests {
|
|
|
1195
1116
|
}
|
|
1196
1117
|
|
|
1197
1118
|
#[test]
|
|
1198
|
-
fn
|
|
1199
|
-
use pep440_rs::VersionSpecifiers;
|
|
1200
|
-
use std::str::FromStr;
|
|
1201
|
-
|
|
1119
|
+
fn test_interpreter_from_metadata_windows() {
|
|
1202
1120
|
// Test cases for different scenarios
|
|
1203
1121
|
let target_x64 = Target::from_resolved_target_triple("x86_64-pc-windows-msvc").unwrap();
|
|
1204
1122
|
let target_x86 = Target::from_resolved_target_triple("i686-pc-windows-msvc").unwrap();
|
|
1205
1123
|
let target_arm64 = Target::from_resolved_target_triple("aarch64-pc-windows-msvc").unwrap();
|
|
1206
1124
|
|
|
1125
|
+
let bridge = BridgeModel::PyO3(PyO3 {
|
|
1126
|
+
crate_name: PyO3Crate::PyO3,
|
|
1127
|
+
version: semver::Version::new(0, 26, 0),
|
|
1128
|
+
abi3: None,
|
|
1129
|
+
metadata: None,
|
|
1130
|
+
});
|
|
1131
|
+
|
|
1132
|
+
let message = |major, minor, platform: &str| InterpreterMetadataMessage {
|
|
1133
|
+
major,
|
|
1134
|
+
minor,
|
|
1135
|
+
interpreter: "cpython".to_string(),
|
|
1136
|
+
implementation_name: "CPython".to_string(),
|
|
1137
|
+
abiflags: None,
|
|
1138
|
+
ext_suffix: Some(".pyd".to_string()),
|
|
1139
|
+
platform: platform.to_string(),
|
|
1140
|
+
executable: None,
|
|
1141
|
+
soabi: None,
|
|
1142
|
+
gil_disabled: false,
|
|
1143
|
+
system: "windows".to_string(),
|
|
1144
|
+
};
|
|
1145
|
+
|
|
1207
1146
|
// Test Python 2.x should be rejected
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1147
|
+
assert_eq!(
|
|
1148
|
+
PythonInterpreter::from_metadata_message(
|
|
1149
|
+
"python2.7",
|
|
1150
|
+
&target_x64,
|
|
1151
|
+
&bridge,
|
|
1152
|
+
message(2, 7, "win-amd64"),
|
|
1153
|
+
)
|
|
1154
|
+
.unwrap_err()
|
|
1155
|
+
.to_string(),
|
|
1156
|
+
"Failed to get information from the python interpreter at python2.7"
|
|
1157
|
+
);
|
|
1216
1158
|
|
|
1217
1159
|
// Test Python 3.x but below minimum version
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1160
|
+
assert_eq!(
|
|
1161
|
+
PythonInterpreter::from_metadata_message(
|
|
1162
|
+
"python3.6",
|
|
1163
|
+
&target_x64,
|
|
1164
|
+
&bridge,
|
|
1165
|
+
message(3, 6, "win-amd64"),
|
|
1166
|
+
)
|
|
1167
|
+
.unwrap_err()
|
|
1168
|
+
.to_string(),
|
|
1169
|
+
"Failed to get information from the python interpreter at python3.6"
|
|
1170
|
+
);
|
|
1226
1171
|
|
|
1227
1172
|
// Test valid Python version with matching platform and architecture
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
&
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1173
|
+
for (target, platform) in &[
|
|
1174
|
+
(&target_x86, "win32"),
|
|
1175
|
+
(&target_x64, "win-amd64"),
|
|
1176
|
+
(&target_arm64, "win-arm64"),
|
|
1177
|
+
] {
|
|
1178
|
+
assert_eq!(
|
|
1179
|
+
PythonInterpreter::from_metadata_message(
|
|
1180
|
+
"python3.10",
|
|
1181
|
+
target,
|
|
1182
|
+
&bridge,
|
|
1183
|
+
message(3, 10, platform),
|
|
1184
|
+
)
|
|
1185
|
+
.unwrap()
|
|
1186
|
+
.unwrap(),
|
|
1187
|
+
PythonInterpreter {
|
|
1188
|
+
config: InterpreterConfig {
|
|
1189
|
+
major: 3,
|
|
1190
|
+
minor: 10,
|
|
1191
|
+
interpreter_kind: InterpreterKind::CPython,
|
|
1192
|
+
abiflags: "".to_string(),
|
|
1193
|
+
ext_suffix: ".pyd".to_string(),
|
|
1194
|
+
pointer_width: None,
|
|
1195
|
+
gil_disabled: false,
|
|
1196
|
+
},
|
|
1197
|
+
executable: PathBuf::from("python3.10"),
|
|
1198
|
+
platform: Some(platform.replace("-", "_")),
|
|
1199
|
+
runnable: true,
|
|
1200
|
+
implementation_name: "CPython".to_string(),
|
|
1201
|
+
soabi: None,
|
|
1202
|
+
}
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1256
1205
|
|
|
1257
1206
|
// Test mismatched architectures
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
&target_x64,
|
|
1262
|
-
"win-arm64"
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
7,
|
|
1306
|
-
Some(&requires_python)
|
|
1307
|
-
));
|
|
1308
|
-
|
|
1309
|
-
// Should reject Python 3.12 due to requires-python upper bound
|
|
1310
|
-
assert!(windows_interpreter_no_build(
|
|
1311
|
-
3,
|
|
1312
|
-
12,
|
|
1313
|
-
&target_x64,
|
|
1314
|
-
"win-amd64".to_string(),
|
|
1315
|
-
7,
|
|
1316
|
-
Some(&requires_python)
|
|
1317
|
-
));
|
|
1318
|
-
|
|
1319
|
-
// Test edge case with unknown platform (should not match any specific architecture)
|
|
1320
|
-
assert!(!windows_interpreter_no_build(
|
|
1321
|
-
3,
|
|
1322
|
-
10,
|
|
1323
|
-
&target_x64,
|
|
1324
|
-
"unknown-platform".to_string(),
|
|
1325
|
-
7,
|
|
1326
|
-
None
|
|
1327
|
-
));
|
|
1207
|
+
for (target, platform) in &[
|
|
1208
|
+
(&target_x86, "win-amd64"),
|
|
1209
|
+
(&target_x86, "win-arm64"),
|
|
1210
|
+
(&target_x64, "win32"),
|
|
1211
|
+
(&target_x64, "win-arm64"),
|
|
1212
|
+
(&target_arm64, "win32"),
|
|
1213
|
+
(&target_arm64, "win-amd64"),
|
|
1214
|
+
] {
|
|
1215
|
+
assert_eq!(
|
|
1216
|
+
PythonInterpreter::from_metadata_message(
|
|
1217
|
+
"python3.10",
|
|
1218
|
+
target,
|
|
1219
|
+
&bridge,
|
|
1220
|
+
message(3, 10, platform),
|
|
1221
|
+
)
|
|
1222
|
+
.unwrap(),
|
|
1223
|
+
None
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// Test edge case with unknown platform (should not match any specific architecture, build anyway)
|
|
1228
|
+
assert_eq!(
|
|
1229
|
+
PythonInterpreter::from_metadata_message(
|
|
1230
|
+
"python3.10",
|
|
1231
|
+
&target_x64,
|
|
1232
|
+
&bridge,
|
|
1233
|
+
message(3, 10, "unknown-platform"),
|
|
1234
|
+
)
|
|
1235
|
+
.unwrap()
|
|
1236
|
+
.unwrap(),
|
|
1237
|
+
PythonInterpreter {
|
|
1238
|
+
config: InterpreterConfig {
|
|
1239
|
+
major: 3,
|
|
1240
|
+
minor: 10,
|
|
1241
|
+
interpreter_kind: InterpreterKind::CPython,
|
|
1242
|
+
abiflags: "".to_string(),
|
|
1243
|
+
ext_suffix: ".pyd".to_string(),
|
|
1244
|
+
pointer_width: None,
|
|
1245
|
+
gil_disabled: false,
|
|
1246
|
+
},
|
|
1247
|
+
executable: PathBuf::from("python3.10"),
|
|
1248
|
+
platform: Some("unknown_platform".to_string()),
|
|
1249
|
+
runnable: true,
|
|
1250
|
+
implementation_name: "CPython".to_string(),
|
|
1251
|
+
soabi: None,
|
|
1252
|
+
}
|
|
1253
|
+
);
|
|
1328
1254
|
}
|
|
1329
1255
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|