@@ -5,7 +5,7 @@ use std::{path::PathBuf, sync::Once};
55
66use common:: { does_version_match, resolve_test_path} ;
77use lazy_static:: lazy_static;
8- use log:: { error, trace} ;
8+ use log:: { error, trace, warn } ;
99use pet:: {
1010 find:: identify_python_executables_using_locators,
1111 locators:: identify_python_environment_using_locators, resolve:: resolve_environment,
@@ -321,13 +321,39 @@ fn verify_validity_of_interpreter_info(environment: PythonEnvironment) {
321321 }
322322 if let Some ( version) = environment. clone ( ) . version {
323323 let expected_version = & interpreter_info. clone ( ) . sys_version ;
324- assert ! (
325- does_version_match( & version, expected_version) ,
326- "Version mismatch for (expected {:?} to start with {:?}) for {:?}" ,
327- expected_version,
328- version,
329- environment. clone( )
330- ) ;
324+ if !does_version_match ( & version, expected_version) {
325+ // For pyenv environments, the version may come from the directory name
326+ // which can be out of sync with the binary during CPython version transitions
327+ // (e.g. pyenv installs pre-built binaries without header files).
328+ // Verify at least major.minor matches.
329+ // See https://github.com/microsoft/python-environment-tools/issues/371
330+ if environment. kind == Some ( PythonEnvironmentKind :: Pyenv ) {
331+ let parts: Vec < & str > = version. splitn ( 3 , '.' ) . collect ( ) ;
332+ let major_minor = if parts. len ( ) >= 2 {
333+ format ! ( "{}.{}" , parts[ 0 ] , parts[ 1 ] )
334+ } else {
335+ version. clone ( )
336+ } ;
337+ assert ! (
338+ expected_version. starts_with( & major_minor) ,
339+ "Version mismatch (even major.minor differs) for (expected {:?} to start with {:?}) for {:?}" ,
340+ expected_version,
341+ major_minor,
342+ environment. clone( )
343+ ) ;
344+ warn ! (
345+ "Pyenv patch version mismatch: detected={:?}, actual starts with {:?}" ,
346+ version, expected_version
347+ ) ;
348+ } else {
349+ panic ! (
350+ "Version mismatch for (expected {:?} to start with {:?}) for {:?}" ,
351+ expected_version,
352+ version,
353+ environment. clone( )
354+ ) ;
355+ }
356+ }
331357 }
332358}
333359
@@ -462,15 +488,36 @@ fn compare_environments(actual: PythonEnvironment, expected: PythonEnvironment,
462488 if let ( Some ( version) , Some ( expected_version) ) =
463489 ( expected. clone ( ) . version , actual. clone ( ) . version )
464490 {
465- assert ! (
466- does_version_match( & version, & expected_version) ,
467- "Version mismatch when using {} for (expected {:?} to start with {:?}) for env = {:?} and environment = {:?}" ,
468- method,
469- expected_version,
470- version,
471- actual. clone( ) ,
472- expected. clone( )
473- ) ;
491+ if !does_version_match ( & version, & expected_version) {
492+ // Pyenv directory name can differ from actual binary version at patch level.
493+ // See https://github.com/microsoft/python-environment-tools/issues/371
494+ if expected. kind == Some ( PythonEnvironmentKind :: Pyenv ) {
495+ let parts: Vec < & str > = version. splitn ( 3 , '.' ) . collect ( ) ;
496+ let major_minor = if parts. len ( ) >= 2 {
497+ format ! ( "{}.{}" , parts[ 0 ] , parts[ 1 ] )
498+ } else {
499+ version. clone ( )
500+ } ;
501+ assert ! (
502+ expected_version. starts_with( & major_minor) ,
503+ "Version mismatch (even major.minor differs) when using {} for (expected {:?} to start with {:?}) for env = {:?} and environment = {:?}" ,
504+ method,
505+ expected_version,
506+ major_minor,
507+ actual. clone( ) ,
508+ expected. clone( )
509+ ) ;
510+ } else {
511+ panic ! (
512+ "Version mismatch when using {} for (expected {:?} to start with {:?}) for env = {:?} and environment = {:?}" ,
513+ method,
514+ expected_version,
515+ version,
516+ actual. clone( ) ,
517+ expected. clone( )
518+ ) ;
519+ }
520+ }
474521 // if !does_version_match(&version, &expected_version) {
475522 // error!("Version mismatch when using {} for (expected {:?} to start with {:?}) for env = {:?} and environment = {:?}",
476523 // method,
0 commit comments