-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds support for detecting and evaluating environment markers. Environment markers can be extracted from a python executable by running a simple python script. Fixes #34 as the proper python markers are now parsed and evaluated: ``` >rip "scipy>=1.4.0" 2023-10-02T13:34:12.758759Z INFO rip: extracted the following environment markers from the system python interpreter: Pep508EnvMakers { os_name: "nt", sys_platform: "win32", platform_machine: "AMD64", platform_python_implementation: "CPython", platform_release: "10", platform_system: "Windows", platform_version: "10.0.22621", python_version: "3.8", python_full_version: "3.8.17", implementation_name: "cpython", implementation_version: "3.8.17", } 2023-10-02T13:34:12.759610Z INFO rattler_installs_packages::resolve: collecting scipy 2023-10-02T13:34:12.759831Z INFO rattler_installs_packages::http: executing request url=https://pypi.org/simple/scipy/ cache_mode=Default 2023-10-02T13:34:12.830482Z WARN rattler_installs_packages::resolve: Not considering scipy 1.11.0rc2, 1.11.0rc1, 1.10.0rc2, 1.10.0rc1, 1.9.0rc3, 1.9.0rc2, 1.9.0rc1, 1.8.0rc4, 1.8.0rc3, 1.8.0rc2, 1.8.0rc1, 0.8.0 because there are no wheel artifacts available 2023-10-02T13:34:12.830699Z WARN rattler_installs_packages::resolve: Not considering scipy 1.11.3, 1.11.2, 1.11.1, 1.11.0 because none of the artifacts are compatible with Python 3.8.17 2023-10-02T13:34:12.831023Z INFO rattler_installs_packages::resolve: obtaining dependency information from scipy=1.10.1 2023-10-02T13:34:12.831685Z INFO rattler_installs_packages::resolve: collecting numpy 2023-10-02T13:34:12.831821Z INFO rattler_installs_packages::http: executing request url=https://pypi.org/simple/numpy/ cache_mode=Default 2023-10-02T13:34:12.874279Z WARN rattler_installs_packages::resolve: Not considering numpy 1.26.0rc1, 1.26.0b1, 1.25.0rc1, 1.24.0rc2, 1.24.0rc1, 1.23.0rc3, 1.23.0rc2, 1.23.0rc1, 1.10.0.post2, 1.5.0, 1.4.1, 1.3.0 because there are no wheel artifacts available 2023-10-02T13:34:12.874502Z WARN rattler_installs_packages::resolve: Not considering numpy 1.26.0, 1.25.2, 1.25.1, 1.25.0 because none of the artifacts are compatible with Python 3.8.17 2023-10-02T13:34:12.874934Z INFO rattler_installs_packages::resolve: collecting scipy[test] 2023-10-02T13:34:12.876837Z INFO rattler_installs_packages::resolve: collecting scipy[dev] 2023-10-02T13:34:12.878637Z INFO rattler_installs_packages::resolve: collecting scipy[doc] 2023-10-02T13:34:12.880546Z INFO rattler_installs_packages::resolve: obtaining dependency information from numpy=1.24.4 Resolved environment: - scipy >= 1.4.0 Name Version numpy 1.24.4 scipy 1.10.1 ``` @notatallshaw You might be interested in this! :) Fix #2
- Loading branch information
1 parent
a7ad26c
commit ab1e94b
Showing
9 changed files
with
296 additions
and
38 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
use crate::marker::Env; | ||
use serde::{Deserialize, Serialize}; | ||
use std::io; | ||
use std::io::ErrorKind; | ||
use std::path::Path; | ||
use std::process::ExitStatus; | ||
use thiserror::Error; | ||
|
||
/// Describes the environment markers that can be used in dependency specifications to enable or | ||
/// disable certain dependencies based on runtime environment. | ||
/// | ||
/// Exactly the markers defined in this struct must be present during version resolution. Unknown | ||
/// variables should raise an error. | ||
/// | ||
/// Note that the "extra" variable is not defined in this struct because it depends on the wheel | ||
/// that is being inspected. | ||
/// | ||
/// The behavior and the names of the markers are described in PEP 508. | ||
#[derive(Default, Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] | ||
#[allow(missing_docs)] | ||
pub struct Pep508EnvMakers { | ||
pub os_name: String, | ||
pub sys_platform: String, | ||
pub platform_machine: String, | ||
pub platform_python_implementation: String, | ||
pub platform_release: String, | ||
pub platform_system: String, | ||
pub platform_version: String, | ||
pub python_version: String, | ||
pub python_full_version: String, | ||
pub implementation_name: String, | ||
pub implementation_version: String, | ||
} | ||
|
||
#[derive(Debug, Error)] | ||
pub enum FromPythonError { | ||
#[error("could not find python executable")] | ||
CouldNotFindPythonExecutable, | ||
|
||
#[error(transparent)] | ||
FailedToExecute(#[from] io::Error), | ||
|
||
#[error(transparent)] | ||
FailedToParse(#[from] serde_json::Error), | ||
|
||
#[error("execution failed with exit code {0}")] | ||
FailedToRun(ExitStatus), | ||
} | ||
|
||
impl Pep508EnvMakers { | ||
/// Try to determine the environment markers by executing python. | ||
pub async fn from_env() -> Result<Self, FromPythonError> { | ||
Self::from_python(Path::new("python")).await | ||
} | ||
|
||
/// Try to determine the environment markers from an existing python executable. The executable | ||
/// is used to run a simple python program to extract the information. | ||
pub async fn from_python(python: &Path) -> Result<Self, FromPythonError> { | ||
let pep508_bytes = include_str!("pep508.py"); | ||
|
||
// Execute the python executable | ||
let output = match tokio::process::Command::new(python) | ||
.arg("-c") | ||
.arg(pep508_bytes) | ||
.output() | ||
.await | ||
{ | ||
Err(e) if e.kind() == ErrorKind::NotFound => { | ||
return Err(FromPythonError::CouldNotFindPythonExecutable) | ||
} | ||
Err(e) => return Err(FromPythonError::FailedToExecute(e)), | ||
Ok(output) => output, | ||
}; | ||
|
||
// Ensure that we have a valid success code | ||
if !output.status.success() { | ||
return Err(FromPythonError::FailedToRun(output.status)); | ||
} | ||
|
||
// Convert the JSON | ||
let stdout = String::from_utf8_lossy(&output.stdout); | ||
Ok(serde_json::from_str(stdout.trim())?) | ||
} | ||
} | ||
|
||
impl Env for Pep508EnvMakers { | ||
fn get_marker_var(&self, var: &str) -> Option<&str> { | ||
match var { | ||
"os_name" => Some(&self.os_name), | ||
"sys_platform" => Some(&self.sys_platform), | ||
"platform_machine" => Some(&self.platform_machine), | ||
"platform_python_implementation" => Some(&self.platform_python_implementation), | ||
"platform_release" => Some(&self.platform_release), | ||
"platform_system" => Some(&self.platform_system), | ||
"platform_version" => Some(&self.platform_version), | ||
"python_version" => Some(&self.python_version), | ||
"python_full_version" => Some(&self.python_full_version), | ||
"implementation_name" => Some(&self.implementation_name), | ||
"implementation_version" => Some(&self.implementation_version), | ||
_ => None, | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
|
||
#[tokio::test] | ||
pub async fn test_from_env() { | ||
match Pep508EnvMakers::from_env().await { | ||
Err(FromPythonError::CouldNotFindPythonExecutable) => { | ||
// This is fine, the test machine does not include a python binary. | ||
} | ||
Err(e) => panic!("{e}"), | ||
Ok(env) => { | ||
println!( | ||
"Found the following environment markers on the current system:\n\n{env:#?}" | ||
) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# A program that outputs PEP 508 environment markers in a JSON format. Most of the | ||
# implementation has been taken from the example in the PEP. | ||
# | ||
# See: https://peps.python.org/pep-0508/ | ||
|
||
import os | ||
import sys | ||
import platform | ||
import json | ||
|
||
|
||
def format_full_version(info): | ||
version = '{0.major}.{0.minor}.{0.micro}'.format(info) | ||
kind = info.releaselevel | ||
if kind != 'final': | ||
version += kind[0] + str(info.serial) | ||
return version | ||
|
||
|
||
if hasattr(sys, 'implementation'): | ||
implementation_version = format_full_version(sys.implementation.version) | ||
implementation_name = sys.implementation.name | ||
else: | ||
implementation_version = '0' | ||
implementation_name = '' | ||
bindings = { | ||
'implementation_name': implementation_name, | ||
'implementation_version': implementation_version, | ||
'os_name': os.name, | ||
'platform_machine': platform.machine(), | ||
'platform_python_implementation': platform.python_implementation(), | ||
'platform_release': platform.release(), | ||
'platform_system': platform.system(), | ||
'platform_version': platform.version(), | ||
'python_full_version': platform.python_version(), | ||
'python_version': '.'.join(platform.python_version_tuple()[:2]), | ||
'sys_platform': sys.platform, | ||
} | ||
|
||
json.dump(bindings, sys.stdout) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.