Skip to content

Commit

Permalink
Merge pull request #1146 from messense/fix-windows-conda
Browse files Browse the repository at this point in the history
Fix `maturin develop` in Windows conda virtual environment
  • Loading branch information
messense authored Sep 29, 2022
2 parents 0b32db4 + 3e27511 commit 0d0d8c4
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 42 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ jobs:
RUST_BACKTRACE: '1'
steps:
- uses: actions/checkout@v3
- uses: conda-incubator/setup-miniconda@v2
with:
auto-activate-base: 'false'
activate-environment: ''
- uses: actions/setup-python@v4
with:
python-version: "3.7"
Expand Down
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

* Fix `maturin develop` in Windows conda virtual environment in [#1146](https://github.com/PyO3/maturin/pull/1146)

## [0.13.5] - 2022-09-27

* Fix resolving crate name bug in [#1142](https://github.com/PyO3/maturin/pull/1142)
Expand Down
4 changes: 2 additions & 2 deletions src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,13 +579,13 @@ impl Target {
let venv = venv_base.as_ref();
if self.is_windows() {
let bin_dir = venv.join("Scripts");
if bin_dir.exists() {
if bin_dir.join("python.exe").exists() {
return bin_dir;
}
// Python innstalled via msys2 on Windows might produce a POSIX-like venv
// See https://github.com/PyO3/maturin/issues/1108
let bin_dir = venv.join("bin");
if bin_dir.exists() {
if bin_dir.join("python.exe").exists() {
return bin_dir;
}
// for conda environment
Expand Down
53 changes: 19 additions & 34 deletions tests/common/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,47 +135,32 @@ pub fn test_integration(
Ok(())
}

/// Creates conda environments
#[cfg(target_os = "windows")]
fn create_conda_env(name: &str, major: usize, minor: usize) {
Command::new("conda")
.arg("create")
.arg("-n")
.arg(name)
.arg(format!("python={}.{}", major, minor))
.arg("-q")
.arg("-y")
.output()
.expect("Conda not available.");
}

#[cfg(target_os = "windows")]
pub fn test_integration_conda(package: impl AsRef<Path>, bindings: Option<String>) -> Result<()> {
use crate::common::create_conda_env;
use std::path::PathBuf;
use std::process::Stdio;

let package_string = package.as_ref().join("Cargo.toml").display().to_string();

// Since the python launcher has precedence over conda, we need to deactivate it.
// We do so by shadowing it with our own hello world binary.
let original_path = env::var_os("PATH").expect("PATH is not defined");
let py_dir = env::current_dir()?
.join("test-data")
.to_str()
.unwrap()
.to_string();
let mocked_path = py_dir + ";" + original_path.to_str().unwrap();
env::set_var("PATH", mocked_path);

// Create environments to build against, prepended with "A" to ensure that integration
// tests are executed with these environments
create_conda_env("A-pyo3-build-env-37", 3, 7);
create_conda_env("A-pyo3-build-env-38", 3, 8);
create_conda_env("A-pyo3-build-env-39", 3, 9);
create_conda_env("A-pyo3-build-env-310", 3, 10);
let mut interpreters = Vec::new();
for minor in 7..=10 {
let (_, venv_python) = create_conda_env(&format!("A-maturin-env-3{}", minor), 3, minor)?;
interpreters.push(venv_python);
}

// The first argument is ignored by clap
let mut cli = vec!["build", "--manifest-path", &package_string, "--quiet"];
let mut cli = vec![
"build",
"--manifest-path",
&package_string,
"--quiet",
"--interpreter",
];
for interp in &interpreters {
cli.push(interp.to_str().unwrap());
}

if let Some(ref bindings) = bindings {
cli.push("--bindings");
Expand All @@ -190,13 +175,13 @@ pub fn test_integration_conda(package: impl AsRef<Path>, bindings: Option<String
let mut conda_wheels: Vec<(PathBuf, PathBuf)> = vec![];
for ((filename, _), python_interpreter) in wheels.iter().zip(build_context.interpreter) {
let executable = python_interpreter.executable;
if executable.to_str().unwrap().contains("pyo3-build-env-") {
if executable.to_str().unwrap().contains("maturin-env-") {
conda_wheels.push((filename.clone(), executable))
}
}

assert_eq!(
3,
interpreters.len(),
conda_wheels.len(),
"Error creating or detecting conda environments."
);
Expand All @@ -215,7 +200,7 @@ pub fn test_integration_conda(package: impl AsRef<Path>, bindings: Option<String
if !output.status.success() {
panic!();
}
check_installed(&package.as_ref(), &executable)?;
check_installed(package.as_ref(), &executable)?;
}

Ok(())
Expand Down
36 changes: 36 additions & 0 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,39 @@ pub fn create_virtualenv(
let python = target.get_venv_python(&venv_dir);
Ok((venv_dir, python))
}

/// Creates conda environments
pub fn create_conda_env(name: &str, major: usize, minor: usize) -> Result<(PathBuf, PathBuf)> {
use serde::Deserialize;

#[derive(Deserialize)]
struct CondaCreateResult {
prefix: PathBuf,
success: bool,
}

let mut cmd = if cfg!(windows) {
let mut cmd = Command::new("cmd.exe");
cmd.arg("/c").arg("conda");
cmd
} else {
Command::new("conda")
};
let output = cmd
.arg("create")
.arg("-n")
.arg(name)
.arg(format!("python={}.{}", major, minor))
.arg("-q")
.arg("-y")
.arg("--json")
.output()
.expect("Conda not available.");
let result: CondaCreateResult = serde_json::from_slice(&output.stdout)?;
if !result.success {
bail!("Failed to create conda environment {}.", name);
}
let target = Target::from_target_triple(None)?;
let python = target.get_venv_python(&result.prefix);
Ok((result.prefix, python))
}
13 changes: 7 additions & 6 deletions tests/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,15 @@ fn integration_pyo3_mixed_py_subdir() {
));
}

#[cfg(target_os = "windows")]
#[test]
#[ignore]
fn integration_pyo3_pure_conda() {
handle_result(integration::test_integration_conda(
"text-crates/pyo3-pure",
None,
));
// Only run on GitHub Actions for now
if std::env::var("GITHUB_ACTIONS").is_ok() {
handle_result(integration::test_integration_conda(
"test-crates/pyo3-mixed",
None,
));
}
}

#[test]
Expand Down

0 comments on commit 0d0d8c4

Please sign in to comment.