Skip to content

Commit

Permalink
pyoxidizer: correctly parse Python X.Y version
Browse files Browse the repository at this point in the history
The version string parsing code didn't handle minor versions with a
length > 1 in all code paths. This commit introduces a helper function
to so version parsing is consistent.

Closes #569.
Closes #600.
  • Loading branch information
codifryed authored and indygreg committed Jul 31, 2022
1 parent ecdaa4b commit 28504bf
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 5 deletions.
3 changes: 3 additions & 0 deletions pyoxidizer/docs/pyoxidizer_history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ Bug Fixes

* Default macOS Python distributions should no longer crash when running
tkinter. This fixes a regression introduced in the 0.20 release.
* The paths to Python modules when using Python 3.10 is now properly resolved.
Before, buggy version string parsing caused various code to look for Python
modules in a ``3.1`` directory instead of ``3.10``. (#569, #600).

Changes
^^^^^^^
Expand Down
50 changes: 45 additions & 5 deletions pyoxidizer/src/py_packaging/standalone_distribution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,18 @@ fn parse_python_json_from_distribution(dist_dir: &Path) -> Result<PythonJsonMain
parse_python_json(&python_json_path)
}

fn parse_python_major_minor_version(version: &str) -> String {
let mut at_least_minor_version = String::from(version);
if !version.contains(".") {
at_least_minor_version.push_str(".0");
}
at_least_minor_version
.split('.')
.take(2)
.collect::<Vec<_>>()
.join(".")
}

/// Resolve the path to a `python` executable in a Python distribution.
pub fn python_exe_path(dist_dir: &Path) -> Result<PathBuf> {
let pi = parse_python_json_from_distribution(dist_dir)?;
Expand Down Expand Up @@ -294,9 +306,10 @@ pub fn resolve_python_paths(base: &Path, python_version: &str) -> PythonPaths {
let mut pyoxidizer_state_dir = p.clone();
pyoxidizer_state_dir.extend(PYOXIDIZER_STATE_DIR.split('/'));

let unix_lib_dir = p
.join("lib")
.join(format!("python{}", &python_version[0..3]));
let unix_lib_dir = p.join("lib").join(format!(
"python{}",
parse_python_major_minor_version(python_version)
));

let stdlib = if unix_lib_dir.exists() {
unix_lib_dir
Expand Down Expand Up @@ -1171,8 +1184,7 @@ impl PythonDistribution for StandaloneDistribution {
}

fn python_major_minor_version(&self) -> String {
let parts = self.version.split('.').take(2).collect::<Vec<_>>();
parts.join(".")
parse_python_major_minor_version(&self.version)
}

fn python_implementation(&self) -> &str {
Expand Down Expand Up @@ -1632,4 +1644,32 @@ pub mod tests {

Ok(())
}

#[test]
fn test_parse_python_major_minor_version() {
let version_expectations = [
("3.7.1", "3.7"),
("3.10.1", "3.10"),
("1.2.3.4.5", "1.2"),
("1", "1.0"),
];
for (version, expected) in version_expectations {
assert_eq!(parse_python_major_minor_version(version), expected);
}
}

#[test]
fn test_resolve_python_paths_site_packages() -> Result<()> {
let python_paths = resolve_python_paths(Path::new("/test/dir"), "3.10.4");
assert_eq!(
python_paths.site_packages.to_str().unwrap(),
"/test/dir/lib/python3.10/site-packages"
);
let python_paths = resolve_python_paths(Path::new("/test/dir"), "3.9.1");
assert_eq!(
python_paths.site_packages.to_str().unwrap(),
"/test/dir/lib/python3.9/site-packages"
);
Ok(())
}
}

0 comments on commit 28504bf

Please sign in to comment.