@@ -34,6 +34,9 @@ use crate::{
34
34
VirtualEnvironment ,
35
35
} ;
36
36
37
+ #[ cfg( windows) ]
38
+ use windows_sys:: Win32 :: Foundation :: { APPMODEL_ERROR_NO_PACKAGE , ERROR_CANT_ACCESS_FILE } ;
39
+
37
40
/// A Python executable and its associated platform markers.
38
41
#[ derive( Debug , Clone ) ]
39
42
pub struct Interpreter {
@@ -760,6 +763,13 @@ pub enum Error {
760
763
#[ source]
761
764
err : io:: Error ,
762
765
} ,
766
+ #[ cfg( windows) ]
767
+ #[ error( "Failed to query Python interpreter at `{path}`" ) ]
768
+ CorruptWindowsPackage {
769
+ path : PathBuf ,
770
+ #[ source]
771
+ err : io:: Error ,
772
+ } ,
763
773
#[ error( "{0}" ) ]
764
774
UnexpectedResponse ( UnexpectedResponseError ) ,
765
775
#[ error( "{0}" ) ]
@@ -872,10 +882,23 @@ impl InterpreterInfo {
872
882
. arg ( "-c" )
873
883
. arg ( script)
874
884
. output ( )
875
- . map_err ( |err| Error :: SpawnFailed {
876
- path : interpreter. to_path_buf ( ) ,
877
- err,
878
- } ) ?;
885
+ . map_err (
886
+ |err| match err. raw_os_error ( ) . and_then ( |code| u32:: try_from ( code) . ok ( ) ) {
887
+ // These error codes are returned if the Python interpreter is a corrupt MSIX
888
+ // package, which we want to differentiate from a typical spawn failure.
889
+ #[ cfg( windows) ]
890
+ Some ( APPMODEL_ERROR_NO_PACKAGE | ERROR_CANT_ACCESS_FILE ) => {
891
+ Error :: CorruptWindowsPackage {
892
+ path : interpreter. to_path_buf ( ) ,
893
+ err,
894
+ }
895
+ }
896
+ _ => Error :: SpawnFailed {
897
+ path : interpreter. to_path_buf ( ) ,
898
+ err,
899
+ } ,
900
+ } ,
901
+ ) ?;
879
902
880
903
if !output. status . success ( ) {
881
904
let stderr = String :: from_utf8_lossy ( & output. stderr ) . trim ( ) . to_string ( ) ;
0 commit comments