@@ -1668,9 +1668,19 @@ fn is_windows_store_shim(_path: &Path) -> bool {
16681668impl PythonVariant {
16691669 fn matches_interpreter ( self , interpreter : & Interpreter ) -> bool {
16701670 match self {
1671- // TODO(zanieb): Right now, we allow debug interpreters to be selected by default for
1672- // backwards compatibility, but we may want to change this in the future.
1673- Self :: Default => !interpreter. gil_disabled ( ) ,
1671+ Self :: Default => {
1672+ // TODO(zanieb): Right now, we allow debug interpreters to be selected by default for
1673+ // backwards compatibility, but we may want to change this in the future.
1674+ if ( interpreter. python_major ( ) , interpreter. python_minor ( ) ) >= ( 3 , 14 ) {
1675+ // For Python 3.14+, the free-threaded build is not considered experimental
1676+ // and can satisfy the default variant without opt-in
1677+ true
1678+ } else {
1679+ // In Python 3.13 and earlier, the free-threaded build is considered
1680+ // experimental and requires explicit opt-in
1681+ !interpreter. gil_disabled ( )
1682+ }
1683+ }
16741684 Self :: Debug => interpreter. debug_enabled ( ) ,
16751685 Self :: Freethreaded => interpreter. gil_disabled ( ) ,
16761686 Self :: FreethreadedDebug => interpreter. gil_disabled ( ) && interpreter. debug_enabled ( ) ,
@@ -1935,6 +1945,24 @@ impl PythonRequest {
19351945 }
19361946 }
19371947
1948+ /// Check if this request includes a specific prerelease version.
1949+ pub fn includes_prerelease ( & self ) -> bool {
1950+ match self {
1951+ Self :: Default => false ,
1952+ Self :: Any => false ,
1953+ Self :: Version ( version_request) => version_request. prerelease ( ) . is_some ( ) ,
1954+ Self :: Directory ( ..) => false ,
1955+ Self :: File ( ..) => false ,
1956+ Self :: ExecutableName ( ..) => false ,
1957+ Self :: Implementation ( ..) => false ,
1958+ Self :: ImplementationVersion ( _, version) => version. prerelease ( ) . is_some ( ) ,
1959+ Self :: Key ( request) => request
1960+ . version
1961+ . as_ref ( )
1962+ . is_some_and ( |request| request. prerelease ( ) . is_some ( ) ) ,
1963+ }
1964+ }
1965+
19381966 /// Check if a given interpreter satisfies the interpreter request.
19391967 pub fn satisfied ( & self , interpreter : & Interpreter , cache : & Cache ) -> bool {
19401968 /// Returns `true` if the two paths refer to the same interpreter executable.
@@ -2555,6 +2583,17 @@ impl VersionRequest {
25552583 }
25562584 }
25572585
2586+ /// Return the pre-release segment of the request, if any.
2587+ pub ( crate ) fn prerelease ( & self ) -> Option < & Prerelease > {
2588+ match self {
2589+ Self :: Any | Self :: Default | Self :: Range ( _, _) => None ,
2590+ Self :: Major ( _, _) => None ,
2591+ Self :: MajorMinor ( _, _, _) => None ,
2592+ Self :: MajorMinorPatch ( _, _, _, _) => None ,
2593+ Self :: MajorMinorPrerelease ( _, _, prerelease, _) => Some ( prerelease) ,
2594+ }
2595+ }
2596+
25582597 /// Check if the request is for a version supported by uv.
25592598 ///
25602599 /// If not, an `Err` is returned with an explanatory message.
@@ -2760,8 +2799,8 @@ impl VersionRequest {
27602799 ) ,
27612800 Self :: MajorMinorPrerelease ( self_major, self_minor, self_prerelease, _) => {
27622801 // Pre-releases of Python versions are always for the zero patch version
2763- ( * self_major, * self_minor, 0 ) == ( major , minor , patch )
2764- && prerelease . is_none_or ( |pre| * self_prerelease == pre )
2802+ ( * self_major, * self_minor, 0 , Some ( * self_prerelease ) )
2803+ == ( major , minor , patch , prerelease )
27652804 }
27662805 }
27672806 }
0 commit comments