Skip to content

Commit

Permalink
Use generic tags when sys.implementation.name != `platform.python_i…
Browse files Browse the repository at this point in the history
…mplementation()`

For example pyston
  • Loading branch information
messense committed Nov 1, 2022
1 parent 530ea4c commit c8e2460
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 41 deletions.
17 changes: 12 additions & 5 deletions src/build_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,10 @@ impl BuildOptions {
let ext_suffix = sysconfig_data
.get("EXT_SUFFIX")
.context("syconfig didn't define an `EXT_SUFFIX` ಠ_ಠ")?;
let abi_tag = sysconfig_data
.get("SOABI")
.and_then(|abi| abi.split('-').nth(1).map(ToString::to_string));
let interpreter_kind = sysconfig_data
.get("SOABI")
let soabi = sysconfig_data.get("SOABI");
let abi_tag =
soabi.and_then(|abi| abi.split('-').nth(1).map(ToString::to_string));
let interpreter_kind = soabi
.and_then(|tag| {
if tag.starts_with("pypy") {
Some(InterpreterKind::PyPy)
Expand All @@ -298,6 +297,8 @@ impl BuildOptions {
executable: PathBuf::new(),
platform: None,
runnable: false,
implmentation_name: interpreter_kind.to_string().to_ascii_lowercase(),
soabi: soabi.cloned(),
});
} else {
if interpreter.is_empty() && !self.find_interpreter {
Expand Down Expand Up @@ -376,6 +377,8 @@ impl BuildOptions {
executable: PathBuf::new(),
platform: None,
runnable: false,
implmentation_name: "cpython".to_string(),
soabi: None,
}])
} else if let Some(interp) = interpreters.get(0) {
println!("🐍 Using {} to generate to link bindings (With abi3, an interpreter is only required on windows)", interp);
Expand All @@ -396,6 +399,8 @@ impl BuildOptions {
executable: PathBuf::new(),
platform: None,
runnable: false,
implmentation_name: "cpython".to_string(),
soabi: None,
}])
} else {
bail!("Failed to find a python interpreter");
Expand Down Expand Up @@ -438,6 +443,8 @@ impl BuildOptions {
executable: PathBuf::new(),
platform: None,
runnable: false,
implmentation_name: "cpython".to_string(),
soabi: None,
}])
} else if target.cross_compiling() {
let mut interps = Vec::with_capacity(found_interpreters.len());
Expand Down
4 changes: 4 additions & 0 deletions src/python_interpreter/get_interpreter_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@
ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")

metadata = {
# sys.implementation.name can differ from platform.python_implementation(), for example
# Pyston has sys.implementation.name == "pyston" while platform.python_implementation() == cpython
"implementation_name": sys.implementation.name,
"executable": sys.executable or None,
"major": sys.version_info.major,
"minor": sys.version_info.minor,
"abiflags": sysconfig.get_config_var("ABIFLAGS"),
"interpreter": platform.python_implementation().lower(),
"ext_suffix": ext_suffix,
"soabi": sysconfig.get_config_var("SOABI") or None,
"abi_tag": (sysconfig.get_config_var("SOABI") or "-").split("-")[1] or None,
"platform": sysconfig.get_platform(),
# This one isn't technically necessary, but still very useful for sanity checks
Expand Down
94 changes: 58 additions & 36 deletions src/python_interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ impl FromStr for InterpreterKind {
/// The output format of [GET_INTERPRETER_METADATA]
#[derive(Deserialize)]
struct InterpreterMetadataMessage {
implementation_name: String,
executable: Option<String>,
major: usize,
minor: usize,
Expand All @@ -328,6 +329,7 @@ struct InterpreterMetadataMessage {
platform: String,
// comes from `platform.system()`
system: String,
soabi: Option<String>,
abi_tag: Option<String>,
}

Expand All @@ -350,6 +352,10 @@ pub struct PythonInterpreter {
/// When cross compile the target interpreter isn't runnable,
/// and it's `executable` is empty
pub runnable: bool,
/// Comes from `sys.platform.name`
pub implmentation_name: String,
/// Comes from sysconfig var `SOABI`
pub soabi: Option<String>,
}

impl Deref for PythonInterpreter {
Expand Down Expand Up @@ -440,41 +446,58 @@ impl PythonInterpreter {
} else {
target.get_platform_tag(platform_tags, universal2)?
};
let tag = match self.interpreter_kind {
InterpreterKind::CPython => {
if target.is_unix() {
format!(
"cp{major}{minor}-cp{major}{minor}{abiflags}-{platform}",
major = self.major,
minor = self.minor,
abiflags = self.abiflags,
platform = platform
)
} else {
// On windows the abiflags are missing, but this seems to work
let tag = if self.implmentation_name.parse::<InterpreterKind>().is_err() {
// Use generic tags when `sys.implementation.name` != `platform.python_implementation()`, for example Pyston
// See also https://github.com/pypa/packaging/blob/0031046f7fad649580bc3127d1cef9157da0dd79/packaging/tags.py#L234-L261
format!(
"{interpreter}{major}{minor}-{soabi}-{platform}",
interpreter = self.implmentation_name,
major = self.major,
minor = self.minor,
soabi = self
.soabi
.as_deref()
.unwrap_or("none")
.replace(['-', '.'], "_"),
platform = platform
)
} else {
match self.interpreter_kind {
InterpreterKind::CPython => {
if target.is_unix() {
format!(
"cp{major}{minor}-cp{major}{minor}{abiflags}-{platform}",
major = self.major,
minor = self.minor,
abiflags = self.abiflags,
platform = platform
)
} else {
// On windows the abiflags are missing, but this seems to work
format!(
"cp{major}{minor}-none-{platform}",
major = self.major,
minor = self.minor,
platform = platform
)
}
}
InterpreterKind::PyPy => {
// pypy uses its version as part of the ABI, e.g.
// pypy 3.7 7.3 => numpy-1.20.1-pp37-pypy37_pp73-manylinux2014_x86_64.whl
format!(
"cp{major}{minor}-none-{platform}",
"pp{major}{minor}-pypy{major}{minor}_{abi_tag}-{platform}",
major = self.major,
minor = self.minor,
platform = platform
// TODO: Proper tag handling for pypy
abi_tag = self
.abi_tag
.clone()
.expect("PyPy's syconfig didn't define an `SOABI` ಠ_ಠ"),
platform = platform,
)
}
}
InterpreterKind::PyPy => {
// pypy uses its version as part of the ABI, e.g.
// pypy 3.7 7.3 => numpy-1.20.1-pp37-pypy37_pp73-manylinux2014_x86_64.whl
format!(
"pp{major}{minor}-pypy{major}{minor}_{abi_tag}-{platform}",
major = self.major,
minor = self.minor,
// TODO: Proper tag handling for pypy
abi_tag = self
.abi_tag
.clone()
.expect("PyPy's syconfig didn't define an `SOABI` ಠ_ಠ"),
platform = platform,
)
}
};
Ok(tag)
}
Expand Down Expand Up @@ -598,13 +621,7 @@ impl PythonInterpreter {
// We don't use platform from sysconfig on macOS
None
} else {
Some(
message
.platform
.to_lowercase()
.replace('-', "_")
.replace('.', "_"),
)
Some(message.platform.to_lowercase().replace(['-', '.'], "_"))
};

Ok(Some(PythonInterpreter {
Expand All @@ -625,16 +642,21 @@ impl PythonInterpreter {
.unwrap_or_else(|| executable.as_ref().to_path_buf()),
platform,
runnable: true,
implmentation_name: message.implementation_name,
soabi: message.soabi,
}))
}

/// Construct a `PythonInterpreter` from a sysconfig and target
pub fn from_config(config: InterpreterConfig) -> Self {
let implmentation_name = config.interpreter_kind.to_string().to_ascii_lowercase();
PythonInterpreter {
config,
executable: PathBuf::new(),
platform: None,
runnable: false,
implmentation_name,
soabi: None,
}
}

Expand Down

0 comments on commit c8e2460

Please sign in to comment.