From 2017756bbae293e16033b7211eea712188d33b90 Mon Sep 17 00:00:00 2001 From: "Tomasz (Tom) Kramkowski" Date: Fri, 23 Jan 2026 13:43:23 +0000 Subject: [PATCH] Use `enumflags2` instead of `bitflags` for Preview --- Cargo.lock | 3 +- Cargo.toml | 1 + crates/uv-auth/src/middleware.rs | 4 +- crates/uv-auth/src/providers.rs | 10 +- crates/uv-auth/src/store.rs | 4 +- crates/uv-build-backend/src/lib.rs | 4 +- crates/uv-build-backend/src/wheel.rs | 6 +- crates/uv-build/src/main.rs | 34 +- crates/uv-cli/src/lib.rs | 4 +- crates/uv-install-wheel/src/linker.rs | 4 +- crates/uv-preview/Cargo.toml | 3 +- crates/uv-preview/src/lib.rs | 404 +++++++++--------- crates/uv-python/src/managed.rs | 4 +- .../src/lock/export/cyclonedx_json.rs | 6 +- crates/uv/src/commands/auth/helper.rs | 6 +- crates/uv/src/commands/cache_size.rs | 6 +- crates/uv/src/commands/pip/compile.rs | 6 +- crates/uv/src/commands/pip/install.rs | 10 +- crates/uv/src/commands/pip/sync.rs | 10 +- crates/uv/src/commands/project/add.rs | 10 +- crates/uv/src/commands/project/format.rs | 6 +- crates/uv/src/commands/project/lock.rs | 10 +- crates/uv/src/commands/project/mod.rs | 4 +- crates/uv/src/commands/project/run.rs | 4 +- crates/uv/src/commands/project/sync.rs | 11 +- crates/uv/src/commands/publish.rs | 6 +- crates/uv/src/commands/python/install.rs | 14 +- crates/uv/src/commands/venv.rs | 4 +- crates/uv/src/commands/workspace/dir.rs | 6 +- crates/uv/src/commands/workspace/list.rs | 6 +- crates/uv/src/commands/workspace/metadata.rs | 6 +- crates/uv/src/lib.rs | 9 +- crates/uv/tests/it/show_settings.rs | 340 +++++++-------- 33 files changed, 482 insertions(+), 483 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0fd11ba983797..13ff6b933f005 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6680,7 +6680,8 @@ dependencies = [ name = "uv-preview" version = "0.0.15" dependencies = [ - "bitflags 2.10.0", + "enumflags2", + "itertools 0.14.0", "thiserror 2.0.17", "uv-warnings", ] diff --git a/Cargo.toml b/Cargo.toml index 1f2308fce14d6..fa34e9eb3e5c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,6 +110,7 @@ dunce = { version = "1.0.5" } either = { version = "1.13.0" } encoding_rs_io = { version = "0.1.7" } embed-manifest = { version = "1.5.0" } +enumflags2 = { version = "0.7.12" } etcetera = { version = "0.11.0" } fastrand = { version = "2.3.0" } flate2 = { version = "1.0.33", default-features = false, features = ["zlib-rs"] } diff --git a/crates/uv-auth/src/middleware.rs b/crates/uv-auth/src/middleware.rs index 005c4e00914ce..8c22dc60a8039 100644 --- a/crates/uv-auth/src/middleware.rs +++ b/crates/uv-auth/src/middleware.rs @@ -8,7 +8,7 @@ use reqwest_middleware::{ClientWithMiddleware, Error, Middleware, Next}; use tokio::sync::Mutex; use tracing::{debug, trace, warn}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_redacted::DisplaySafeUrl; use uv_static::EnvVars; use uv_warnings::owo_colors::OwoColorize; @@ -815,7 +815,7 @@ impl AuthMiddleware { debug!("Found credentials in plaintext store for {url}"); Some(credentials) } else if let Some(credentials) = { - if self.preview.is_enabled(PreviewFeatures::NATIVE_AUTH) { + if self.preview.is_enabled(PreviewFeature::NativeAuth) { let native_store = KeyringProvider::native(); let username = credentials.and_then(|credentials| credentials.username()); let display_username = if let Some(username) = username { diff --git a/crates/uv-auth/src/providers.rs b/crates/uv-auth/src/providers.rs index cf5c7ce4ff534..9b92fc7a3aea2 100644 --- a/crates/uv-auth/src/providers.rs +++ b/crates/uv-auth/src/providers.rs @@ -6,7 +6,7 @@ use reqsign::google::DefaultSigner as GcsDefaultSigner; use tracing::debug; use url::Url; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_static::EnvVars; use uv_warnings::warn_user_once; @@ -70,10 +70,10 @@ impl S3EndpointProvider { /// Returns `true` if the URL matches the configured S3 endpoint. pub(crate) fn is_s3_endpoint(url: &Url, preview: Preview) -> bool { if let Some(s3_endpoint_realm) = S3_ENDPOINT_REALM.as_ref().map(RealmRef::from) { - if !preview.is_enabled(PreviewFeatures::S3_ENDPOINT) { + if !preview.is_enabled(PreviewFeature::S3Endpoint) { warn_user_once!( "The `s3-endpoint` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::S3_ENDPOINT + PreviewFeature::S3Endpoint ); } @@ -119,10 +119,10 @@ impl GcsEndpointProvider { /// Returns `true` if the URL matches the configured GCS endpoint. pub(crate) fn is_gcs_endpoint(url: &Url, preview: Preview) -> bool { if let Some(gcs_endpoint_realm) = GCS_ENDPOINT_REALM.as_ref().map(RealmRef::from) { - if !preview.is_enabled(PreviewFeatures::GCS_ENDPOINT) { + if !preview.is_enabled(PreviewFeature::GcsEndpoint) { warn_user_once!( "The `gcs-endpoint` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::GCS_ENDPOINT + PreviewFeature::GcsEndpoint ); } diff --git a/crates/uv-auth/src/store.rs b/crates/uv-auth/src/store.rs index 19a54192ff847..8810e24fc5935 100644 --- a/crates/uv-auth/src/store.rs +++ b/crates/uv-auth/src/store.rs @@ -6,7 +6,7 @@ use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use thiserror::Error; use uv_fs::{LockedFile, LockedFileError, LockedFileMode, with_added_extension}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_redacted::DisplaySafeUrl; use uv_state::{StateBucket, StateStore}; @@ -30,7 +30,7 @@ pub enum AuthBackend { impl AuthBackend { pub async fn from_settings(preview: Preview) -> Result { // If preview is enabled, we'll use the system-native store - if preview.is_enabled(PreviewFeatures::NATIVE_AUTH) { + if preview.is_enabled(PreviewFeature::NativeAuth) { return Ok(Self::System(KeyringProvider::native())); } diff --git a/crates/uv-build-backend/src/lib.rs b/crates/uv-build-backend/src/lib.rs index 82ae3f63ec14e..ded8627cf88e1 100644 --- a/crates/uv-build-backend/src/lib.rs +++ b/crates/uv-build-backend/src/lib.rs @@ -453,7 +453,7 @@ mod tests { use tempfile::TempDir; use uv_distribution_filename::{SourceDistFilename, WheelFilename}; use uv_fs::{copy_dir_all, relative_to}; - use uv_preview::{Preview, PreviewFeatures}; + use uv_preview::{Preview, PreviewFeature}; const MOCK_UV_VERSION: &str = "1.0.0+test"; @@ -1810,7 +1810,7 @@ mod tests { let build = build( src.path(), dist.path(), - Preview::new(PreviewFeatures::METADATA_JSON), + Preview::new(&[PreviewFeature::MetadataJson]), ) .unwrap(); diff --git a/crates/uv-build-backend/src/wheel.rs b/crates/uv-build-backend/src/wheel.rs index 9c7a817c4d262..254a686ce8fb4 100644 --- a/crates/uv-build-backend/src/wheel.rs +++ b/crates/uv-build-backend/src/wheel.rs @@ -16,7 +16,7 @@ use uv_distribution_filename::WheelFilename; use uv_fs::Simplified; use uv_globfilter::{GlobDirFilter, PortableGlobParser}; use uv_platform_tags::{AbiTag, LanguageTag, PlatformTag}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_warnings::warn_user_once; use crate::metadata::DEFAULT_EXCLUDES; @@ -611,7 +611,7 @@ fn write_dist_info( &format!("{dist_info_dir}/WHEEL"), wheel_info.to_string().as_bytes(), )?; - if preview.is_enabled(PreviewFeatures::METADATA_JSON) { + if preview.is_enabled(PreviewFeature::MetadataJson) { writer.write_bytes( &format!("{dist_info_dir}/WHEEL.json"), &serde_json::to_vec(&wheel_info).map_err(Error::Json)?, @@ -632,7 +632,7 @@ fn write_dist_info( &format!("{dist_info_dir}/METADATA"), metadata.core_metadata_format().as_bytes(), )?; - if preview.is_enabled(PreviewFeatures::METADATA_JSON) { + if preview.is_enabled(PreviewFeature::MetadataJson) { writer.write_bytes( &format!("{dist_info_dir}/METADATA.json"), &serde_json::to_vec(&metadata).map_err(Error::Json)?, diff --git a/crates/uv-build/src/main.rs b/crates/uv-build/src/main.rs index 6f5d138743da7..927c8cfc8f339 100644 --- a/crates/uv-build/src/main.rs +++ b/crates/uv-build/src/main.rs @@ -2,7 +2,7 @@ use std::env; use std::io::Write; use std::path::PathBuf; use std::str::FromStr; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::Preview; use uv_static::{EnvVars, parse_boolish_environment_variable}; use anyhow::{Context, Result, bail}; @@ -42,23 +42,21 @@ fn main() -> Result<()> { .to_string(); // Ad-hoc preview features parsing due to a lack of clap CLI in uv-build. - let preview_features = - if parse_boolish_environment_variable(EnvVars::UV_PREVIEW)?.unwrap_or(false) { - PreviewFeatures::all() - } else if let Some(preview_features) = env::var_os(EnvVars::UV_PREVIEW_FEATURES) { - let preview_features = preview_features - .to_str() - .with_context(|| format!("Invalid UTF-8 in `{}`", EnvVars::UV_PREVIEW_FEATURES))?; - PreviewFeatures::from_str(preview_features).with_context(|| { - format!( - "Invalid preview features list in `{}`", - EnvVars::UV_PREVIEW_FEATURES - ) - })? - } else { - PreviewFeatures::default() - }; - let preview = Preview::new(preview_features); + let preview = if parse_boolish_environment_variable(EnvVars::UV_PREVIEW)?.unwrap_or(false) { + Preview::all() + } else if let Some(preview_features) = env::var_os(EnvVars::UV_PREVIEW_FEATURES) { + let preview_features = preview_features + .to_str() + .with_context(|| format!("Invalid UTF-8 in `{}`", EnvVars::UV_PREVIEW_FEATURES))?; + Preview::from_str(preview_features).with_context(|| { + format!( + "Invalid preview features list in `{}`", + EnvVars::UV_PREVIEW_FEATURES + ) + })? + } else { + Preview::default() + }; match command.as_str() { "build-sdist" => { let sdist_directory = PathBuf::from(args.next().context("Missing sdist directory")?); diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index c9d282727b781..5be5f1c5645ff 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -23,7 +23,7 @@ use uv_distribution_types::{ }; use uv_normalize::{ExtraName, GroupName, PackageName, PipGroupName}; use uv_pep508::{MarkerTree, Requirement}; -use uv_preview::PreviewFeatures; +use uv_preview::PreviewFeature; use uv_pypi_types::VerbatimParsedUrl; use uv_python::{PythonDownloads, PythonPreference, PythonVersion}; use uv_redacted::DisplaySafeUrl; @@ -306,7 +306,7 @@ pub struct GlobalArgs { alias = "preview-feature", value_enum, )] - pub preview_features: Vec, + pub preview_features: Vec, /// Avoid discovering a `pyproject.toml` or `uv.toml` file [env: UV_ISOLATED=] /// diff --git a/crates/uv-install-wheel/src/linker.rs b/crates/uv-install-wheel/src/linker.rs index 4cd667c868902..cd422d06ddb9b 100644 --- a/crates/uv-install-wheel/src/linker.rs +++ b/crates/uv-install-wheel/src/linker.rs @@ -16,7 +16,7 @@ use walkdir::WalkDir; use uv_distribution_filename::WheelFilename; use uv_fs::Simplified; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_warnings::{warn_user, warn_user_once}; use crate::Error; @@ -104,7 +104,7 @@ impl Locks { // This warning is currently in preview. if !self .preview - .is_enabled(PreviewFeatures::DETECT_MODULE_CONFLICTS) + .is_enabled(PreviewFeature::DetectModuleConflicts) { return Ok(()); } diff --git a/crates/uv-preview/Cargo.toml b/crates/uv-preview/Cargo.toml index 68e6263ae3546..5beb3712f1b00 100644 --- a/crates/uv-preview/Cargo.toml +++ b/crates/uv-preview/Cargo.toml @@ -18,7 +18,8 @@ workspace = true [dependencies] uv-warnings = { workspace = true } -bitflags = { workspace = true } +enumflags2 = { workspace = true } +itertools = { workspace = true } thiserror = { workspace = true } [dev-dependencies] diff --git a/crates/uv-preview/src/lib.rs b/crates/uv-preview/src/lib.rs index 3bf01778be60a..15eba59c19f86 100644 --- a/crates/uv-preview/src/lib.rs +++ b/crates/uv-preview/src/lib.rs @@ -1,160 +1,135 @@ use std::{ fmt::{Display, Formatter}, + ops::BitOr, str::FromStr, }; +use enumflags2::{BitFlags, bitflags}; use thiserror::Error; use uv_warnings::warn_user_once; -bitflags::bitflags! { - #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] - pub struct PreviewFeatures: u32 { - const PYTHON_INSTALL_DEFAULT = 1 << 0; - const PYTHON_UPGRADE = 1 << 1; - const JSON_OUTPUT = 1 << 2; - const PYLOCK = 1 << 3; - const ADD_BOUNDS = 1 << 4; - const PACKAGE_CONFLICTS = 1 << 5; - const EXTRA_BUILD_DEPENDENCIES = 1 << 6; - const DETECT_MODULE_CONFLICTS = 1 << 7; - const FORMAT = 1 << 8; - const NATIVE_AUTH = 1 << 9; - const S3_ENDPOINT = 1 << 10; - const CACHE_SIZE = 1 << 11; - const INIT_PROJECT_FLAG = 1 << 12; - const WORKSPACE_METADATA = 1 << 13; - const WORKSPACE_DIR = 1 << 14; - const WORKSPACE_LIST = 1 << 15; - const SBOM_EXPORT = 1 << 16; - const AUTH_HELPER = 1 << 17; - const DIRECT_PUBLISH = 1 << 18; - const TARGET_WORKSPACE_DISCOVERY = 1 << 19; - const METADATA_JSON = 1 << 20; - const GCS_ENDPOINT = 1 << 21; - const ADJUST_ULIMIT = 1 << 22; - } +#[bitflags] +#[repr(u32)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PreviewFeature { + PythonInstallDefault = 1 << 0, + PythonUpgrade = 1 << 1, + JsonOutput = 1 << 2, + Pylock = 1 << 3, + AddBounds = 1 << 4, + PackageConflicts = 1 << 5, + ExtraBuildDependencies = 1 << 6, + DetectModuleConflicts = 1 << 7, + Format = 1 << 8, + NativeAuth = 1 << 9, + S3Endpoint = 1 << 10, + CacheSize = 1 << 11, + InitProjectFlag = 1 << 12, + WorkspaceMetadata = 1 << 13, + WorkspaceDir = 1 << 14, + WorkspaceList = 1 << 15, + SbomExport = 1 << 16, + AuthHelper = 1 << 17, + DirectPublish = 1 << 18, + TargetWorkspaceDiscovery = 1 << 19, + MetadataJson = 1 << 20, + GcsEndpoint = 1 << 21, + AdjustUlimit = 1 << 22, } -impl PreviewFeatures { +impl PreviewFeature { /// Returns the string representation of a single preview feature flag. - /// - /// Panics if given a combination of flags. - fn flag_as_str(self) -> &'static str { + fn as_str(self) -> &'static str { match self { - Self::PYTHON_INSTALL_DEFAULT => "python-install-default", - Self::PYTHON_UPGRADE => "python-upgrade", - Self::JSON_OUTPUT => "json-output", - Self::PYLOCK => "pylock", - Self::ADD_BOUNDS => "add-bounds", - Self::PACKAGE_CONFLICTS => "package-conflicts", - Self::EXTRA_BUILD_DEPENDENCIES => "extra-build-dependencies", - Self::DETECT_MODULE_CONFLICTS => "detect-module-conflicts", - Self::FORMAT => "format", - Self::NATIVE_AUTH => "native-auth", - Self::S3_ENDPOINT => "s3-endpoint", - Self::CACHE_SIZE => "cache-size", - Self::INIT_PROJECT_FLAG => "init-project-flag", - Self::WORKSPACE_METADATA => "workspace-metadata", - Self::WORKSPACE_DIR => "workspace-dir", - Self::WORKSPACE_LIST => "workspace-list", - Self::SBOM_EXPORT => "sbom-export", - Self::AUTH_HELPER => "auth-helper", - Self::DIRECT_PUBLISH => "direct-publish", - Self::TARGET_WORKSPACE_DISCOVERY => "target-workspace-discovery", - Self::METADATA_JSON => "metadata-json", - Self::GCS_ENDPOINT => "gcs-endpoint", - Self::ADJUST_ULIMIT => "adjust-ulimit", - _ => panic!("`flag_as_str` can only be used for exactly one feature flag"), + Self::PythonInstallDefault => "python-install-default", + Self::PythonUpgrade => "python-upgrade", + Self::JsonOutput => "json-output", + Self::Pylock => "pylock", + Self::AddBounds => "add-bounds", + Self::PackageConflicts => "package-conflicts", + Self::ExtraBuildDependencies => "extra-build-dependencies", + Self::DetectModuleConflicts => "detect-module-conflicts", + Self::Format => "format", + Self::NativeAuth => "native-auth", + Self::S3Endpoint => "s3-endpoint", + Self::CacheSize => "cache-size", + Self::InitProjectFlag => "init-project-flag", + Self::WorkspaceMetadata => "workspace-metadata", + Self::WorkspaceDir => "workspace-dir", + Self::WorkspaceList => "workspace-list", + Self::SbomExport => "sbom-export", + Self::AuthHelper => "auth-helper", + Self::DirectPublish => "direct-publish", + Self::TargetWorkspaceDiscovery => "target-workspace-discovery", + Self::MetadataJson => "metadata-json", + Self::GcsEndpoint => "gcs-endpoint", + Self::AdjustUlimit => "adjust-ulimit", } } } -impl Display for PreviewFeatures { +impl Display for PreviewFeature { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - if self.is_empty() { - write!(f, "none") - } else { - let features: Vec<&str> = self.iter().map(Self::flag_as_str).collect(); - write!(f, "{}", features.join(",")) - } + write!(f, "{}", self.as_str()) } } #[derive(Debug, Error, Clone)] -pub enum PreviewFeaturesParseError { - #[error("Empty string in preview features: {0}")] - Empty(String), -} +#[error("Unknown feature flag")] +pub struct PreviewFeatureParseError; -impl FromStr for PreviewFeatures { - type Err = PreviewFeaturesParseError; +impl FromStr for PreviewFeature { + type Err = PreviewFeatureParseError; fn from_str(s: &str) -> Result { - let mut flags = Self::empty(); - - for part in s.split(',') { - let part = part.trim(); - if part.is_empty() { - return Err(PreviewFeaturesParseError::Empty( - "Empty string in preview features".to_string(), - )); - } - - let flag = match part { - "python-install-default" => Self::PYTHON_INSTALL_DEFAULT, - "python-upgrade" => Self::PYTHON_UPGRADE, - "json-output" => Self::JSON_OUTPUT, - "pylock" => Self::PYLOCK, - "add-bounds" => Self::ADD_BOUNDS, - "package-conflicts" => Self::PACKAGE_CONFLICTS, - "extra-build-dependencies" => Self::EXTRA_BUILD_DEPENDENCIES, - "detect-module-conflicts" => Self::DETECT_MODULE_CONFLICTS, - "format" => Self::FORMAT, - "native-auth" => Self::NATIVE_AUTH, - "s3-endpoint" => Self::S3_ENDPOINT, - "gcs-endpoint" => Self::GCS_ENDPOINT, - "cache-size" => Self::CACHE_SIZE, - "init-project-flag" => Self::INIT_PROJECT_FLAG, - "workspace-metadata" => Self::WORKSPACE_METADATA, - "workspace-dir" => Self::WORKSPACE_DIR, - "workspace-list" => Self::WORKSPACE_LIST, - "sbom-export" => Self::SBOM_EXPORT, - "auth-helper" => Self::AUTH_HELPER, - "direct-publish" => Self::DIRECT_PUBLISH, - "target-workspace-discovery" => Self::TARGET_WORKSPACE_DISCOVERY, - "metadata-json" => Self::METADATA_JSON, - "adjust-ulimit" => Self::ADJUST_ULIMIT, - _ => { - warn_user_once!("Unknown preview feature: `{part}`"); - continue; - } - }; - flags |= flag; - } - - Ok(flags) + Ok(match s { + "python-install-default" => Self::PythonInstallDefault, + "python-upgrade" => Self::PythonUpgrade, + "json-output" => Self::JsonOutput, + "pylock" => Self::Pylock, + "add-bounds" => Self::AddBounds, + "package-conflicts" => Self::PackageConflicts, + "extra-build-dependencies" => Self::ExtraBuildDependencies, + "detect-module-conflicts" => Self::DetectModuleConflicts, + "format" => Self::Format, + "native-auth" => Self::NativeAuth, + "s3-endpoint" => Self::S3Endpoint, + "gcs-endpoint" => Self::GcsEndpoint, + "cache-size" => Self::CacheSize, + "init-project-flag" => Self::InitProjectFlag, + "workspace-metadata" => Self::WorkspaceMetadata, + "workspace-dir" => Self::WorkspaceDir, + "workspace-list" => Self::WorkspaceList, + "sbom-export" => Self::SbomExport, + "auth-helper" => Self::AuthHelper, + "direct-publish" => Self::DirectPublish, + "target-workspace-discovery" => Self::TargetWorkspaceDiscovery, + "metadata-json" => Self::MetadataJson, + "adjust-ulimit" => Self::AdjustUlimit, + _ => return Err(PreviewFeatureParseError), + }) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub struct Preview { - flags: PreviewFeatures, + flags: BitFlags, } impl Preview { - pub fn new(flags: PreviewFeatures) -> Self { - Self { flags } + pub fn new(flags: &[PreviewFeature]) -> Self { + Self { + flags: flags.iter().copied().fold(BitFlags::empty(), BitOr::bitor), + } } pub fn all() -> Self { - Self::new(PreviewFeatures::all()) + Self { + flags: BitFlags::all(), + } } - pub fn from_args( - preview: bool, - no_preview: bool, - preview_features: &[PreviewFeatures], - ) -> Self { + pub fn from_args(preview: bool, no_preview: bool, preview_features: &[PreviewFeature]) -> Self { if no_preview { return Self::default(); } @@ -163,16 +138,11 @@ impl Preview { return Self::all(); } - let mut flags = PreviewFeatures::empty(); - - for features in preview_features { - flags |= *features; - } - - Self { flags } + Self::new(preview_features) } - pub fn is_enabled(&self, flag: PreviewFeatures) -> bool { + /// Check if a single feature is enabled + pub fn is_enabled(&self, flag: PreviewFeature) -> bool { self.flags.contains(flag) } } @@ -181,11 +151,47 @@ impl Display for Preview { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { if self.flags.is_empty() { write!(f, "disabled") - } else if self.flags == PreviewFeatures::all() { + } else if self.flags.is_all() { write!(f, "enabled") } else { - write!(f, "{}", self.flags) + write!( + f, + "{}", + itertools::join(self.flags.iter().map(PreviewFeature::as_str), ",") + ) + } + } +} + +#[derive(Debug, Error, Clone)] +pub enum PreviewParseError { + #[error("Empty string in preview features: {0}")] + Empty(String), +} + +impl FromStr for Preview { + type Err = PreviewParseError; + + fn from_str(s: &str) -> Result { + let mut flags = BitFlags::empty(); + + for part in s.split(',') { + let part = part.trim(); + if part.is_empty() { + return Err(PreviewParseError::Empty( + "Empty string in preview features".to_string(), + )); + } + + match PreviewFeature::from_str(part) { + Ok(flag) => flags |= flag, + Err(_) => { + warn_user_once!("Unknown preview feature: `{part}`"); + } + } } + + Ok(Self { flags }) } } @@ -194,46 +200,37 @@ mod tests { use super::*; #[test] - fn test_preview_features_from_str() { + fn test_preview_feature_from_str() { + let features = PreviewFeature::from_str("python-install-default").unwrap(); + assert_eq!(features, PreviewFeature::PythonInstallDefault); + } + + #[test] + fn test_preview_from_str() { // Test single feature - let features = PreviewFeatures::from_str("python-install-default").unwrap(); - assert_eq!(features, PreviewFeatures::PYTHON_INSTALL_DEFAULT); + let preview = Preview::from_str("python-install-default").unwrap(); + assert_eq!(preview.flags, PreviewFeature::PythonInstallDefault); // Test multiple features - let features = PreviewFeatures::from_str("python-upgrade,json-output").unwrap(); - assert!(features.contains(PreviewFeatures::PYTHON_UPGRADE)); - assert!(features.contains(PreviewFeatures::JSON_OUTPUT)); - assert!(!features.contains(PreviewFeatures::PYLOCK)); + let preview = Preview::from_str("python-upgrade,json-output").unwrap(); + assert!(preview.is_enabled(PreviewFeature::PythonUpgrade)); + assert!(preview.is_enabled(PreviewFeature::JsonOutput)); + assert_eq!(preview.flags.bits().count_ones(), 2); // Test with whitespace - let features = PreviewFeatures::from_str("pylock , add-bounds").unwrap(); - assert!(features.contains(PreviewFeatures::PYLOCK)); - assert!(features.contains(PreviewFeatures::ADD_BOUNDS)); + let preview = Preview::from_str("pylock , add-bounds").unwrap(); + assert!(preview.is_enabled(PreviewFeature::Pylock)); + assert!(preview.is_enabled(PreviewFeature::AddBounds)); // Test empty string error - assert!(PreviewFeatures::from_str("").is_err()); - assert!(PreviewFeatures::from_str("pylock,").is_err()); - assert!(PreviewFeatures::from_str(",pylock").is_err()); + assert!(Preview::from_str("").is_err()); + assert!(Preview::from_str("pylock,").is_err()); + assert!(Preview::from_str(",pylock").is_err()); // Test unknown feature (should be ignored with warning) - let features = PreviewFeatures::from_str("unknown-feature,pylock").unwrap(); - assert!(features.contains(PreviewFeatures::PYLOCK)); - assert_eq!(features.bits().count_ones(), 1); - } - - #[test] - fn test_preview_features_display() { - // Test empty - let features = PreviewFeatures::empty(); - assert_eq!(features.to_string(), "none"); - - // Test single feature - let features = PreviewFeatures::PYTHON_INSTALL_DEFAULT; - assert_eq!(features.to_string(), "python-install-default"); - - // Test multiple features - let features = PreviewFeatures::PYTHON_UPGRADE | PreviewFeatures::JSON_OUTPUT; - assert_eq!(features.to_string(), "python-upgrade,json-output"); + let preview = Preview::from_str("unknown-feature,pylock").unwrap(); + assert!(preview.is_enabled(PreviewFeature::Pylock)); + assert_eq!(preview.flags.bits().count_ones(), 1); } #[test] @@ -241,18 +238,28 @@ mod tests { // Test disabled let preview = Preview::default(); assert_eq!(preview.to_string(), "disabled"); + let preview = Preview::new(&[]); + assert_eq!(preview.to_string(), "disabled"); // Test enabled (all features) let preview = Preview::all(); assert_eq!(preview.to_string(), "enabled"); - // Test specific features - let preview = Preview::new(PreviewFeatures::PYTHON_UPGRADE | PreviewFeatures::PYLOCK); + // Test single feature + let preview = Preview::new(&[PreviewFeature::PythonInstallDefault]); + assert_eq!(preview.to_string(), "python-install-default"); + + // Test multiple features + let preview = Preview::new(&[PreviewFeature::PythonUpgrade, PreviewFeature::Pylock]); assert_eq!(preview.to_string(), "python-upgrade,pylock"); } #[test] fn test_preview_from_args() { + // Test no preview and no no_preview, and no features + let preview = Preview::from_args(false, false, &[]); + assert_eq!(preview.to_string(), "disabled"); + // Test no_preview let preview = Preview::from_args(true, true, &[]); assert_eq!(preview.to_string(), "disabled"); @@ -262,67 +269,58 @@ mod tests { assert_eq!(preview.to_string(), "enabled"); // Test specific features - let features = vec![ - PreviewFeatures::PYTHON_UPGRADE, - PreviewFeatures::JSON_OUTPUT, - ]; + let features = vec![PreviewFeature::PythonUpgrade, PreviewFeature::JsonOutput]; let preview = Preview::from_args(false, false, &features); - assert!(preview.is_enabled(PreviewFeatures::PYTHON_UPGRADE)); - assert!(preview.is_enabled(PreviewFeatures::JSON_OUTPUT)); - assert!(!preview.is_enabled(PreviewFeatures::PYLOCK)); + assert!(preview.is_enabled(PreviewFeature::PythonUpgrade)); + assert!(preview.is_enabled(PreviewFeature::JsonOutput)); + assert!(!preview.is_enabled(PreviewFeature::Pylock)); } #[test] - fn test_as_str_single_flags() { + fn test_preview_feature_as_str() { assert_eq!( - PreviewFeatures::PYTHON_INSTALL_DEFAULT.flag_as_str(), + PreviewFeature::PythonInstallDefault.as_str(), "python-install-default" ); + assert_eq!(PreviewFeature::PythonUpgrade.as_str(), "python-upgrade"); + assert_eq!(PreviewFeature::JsonOutput.as_str(), "json-output"); + assert_eq!(PreviewFeature::Pylock.as_str(), "pylock"); + assert_eq!(PreviewFeature::AddBounds.as_str(), "add-bounds"); assert_eq!( - PreviewFeatures::PYTHON_UPGRADE.flag_as_str(), - "python-upgrade" - ); - assert_eq!(PreviewFeatures::JSON_OUTPUT.flag_as_str(), "json-output"); - assert_eq!(PreviewFeatures::PYLOCK.flag_as_str(), "pylock"); - assert_eq!(PreviewFeatures::ADD_BOUNDS.flag_as_str(), "add-bounds"); - assert_eq!( - PreviewFeatures::PACKAGE_CONFLICTS.flag_as_str(), + PreviewFeature::PackageConflicts.as_str(), "package-conflicts" ); assert_eq!( - PreviewFeatures::EXTRA_BUILD_DEPENDENCIES.flag_as_str(), + PreviewFeature::ExtraBuildDependencies.as_str(), "extra-build-dependencies" ); assert_eq!( - PreviewFeatures::DETECT_MODULE_CONFLICTS.flag_as_str(), + PreviewFeature::DetectModuleConflicts.as_str(), "detect-module-conflicts" ); - assert_eq!(PreviewFeatures::FORMAT.flag_as_str(), "format"); - assert_eq!(PreviewFeatures::S3_ENDPOINT.flag_as_str(), "s3-endpoint"); - assert_eq!(PreviewFeatures::GCS_ENDPOINT.flag_as_str(), "gcs-endpoint"); - assert_eq!(PreviewFeatures::SBOM_EXPORT.flag_as_str(), "sbom-export"); + assert_eq!(PreviewFeature::Format.as_str(), "format"); + assert_eq!(PreviewFeature::NativeAuth.as_str(), "native-auth"); + assert_eq!(PreviewFeature::S3Endpoint.as_str(), "s3-endpoint"); + assert_eq!(PreviewFeature::CacheSize.as_str(), "cache-size"); assert_eq!( - PreviewFeatures::DIRECT_PUBLISH.flag_as_str(), - "direct-publish" - ); - assert_eq!( - PreviewFeatures::TARGET_WORKSPACE_DISCOVERY.flag_as_str(), - "target-workspace-discovery" + PreviewFeature::InitProjectFlag.as_str(), + "init-project-flag" ); assert_eq!( - PreviewFeatures::METADATA_JSON.flag_as_str(), - "metadata-json" + PreviewFeature::WorkspaceMetadata.as_str(), + "workspace-metadata" ); + assert_eq!(PreviewFeature::WorkspaceDir.as_str(), "workspace-dir"); + assert_eq!(PreviewFeature::WorkspaceList.as_str(), "workspace-list"); + assert_eq!(PreviewFeature::SbomExport.as_str(), "sbom-export"); + assert_eq!(PreviewFeature::AuthHelper.as_str(), "auth-helper"); + assert_eq!(PreviewFeature::DirectPublish.as_str(), "direct-publish"); assert_eq!( - PreviewFeatures::ADJUST_ULIMIT.flag_as_str(), - "adjust-ulimit" + PreviewFeature::TargetWorkspaceDiscovery.as_str(), + "target-workspace-discovery" ); - } - - #[test] - #[should_panic(expected = "`flag_as_str` can only be used for exactly one feature flag")] - fn test_as_str_multiple_flags_panics() { - let features = PreviewFeatures::PYTHON_UPGRADE | PreviewFeatures::JSON_OUTPUT; - let _ = features.flag_as_str(); + assert_eq!(PreviewFeature::MetadataJson.as_str(), "metadata-json"); + assert_eq!(PreviewFeature::GcsEndpoint.as_str(), "gcs-endpoint"); + assert_eq!(PreviewFeature::AdjustUlimit.as_str(), "adjust-ulimit"); } } diff --git a/crates/uv-python/src/managed.rs b/crates/uv-python/src/managed.rs index 670f8366a202d..a92bab17ff5fb 100644 --- a/crates/uv-python/src/managed.rs +++ b/crates/uv-python/src/managed.rs @@ -12,7 +12,7 @@ use fs_err as fs; use itertools::Itertools; use thiserror::Error; use tracing::{debug, warn}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; #[cfg(windows)] use windows::Win32::Storage::FileSystem::FILE_ATTRIBUTE_REPARSE_POINT; @@ -807,7 +807,7 @@ impl PythonMinorVersionLink { // If preview mode is disabled, still return a `MinorVersionSymlink` for // existing symlinks, allowing continued operations without the `--preview` // flag after initial symlink directory installation. - if !preview.is_enabled(PreviewFeatures::PYTHON_UPGRADE) && !minor_version_link.exists() { + if !preview.is_enabled(PreviewFeature::PythonUpgrade) && !minor_version_link.exists() { return None; } Some(minor_version_link) diff --git a/crates/uv-resolver/src/lock/export/cyclonedx_json.rs b/crates/uv-resolver/src/lock/export/cyclonedx_json.rs index 9f4a7eb4e6a46..abf82ecf3e95b 100644 --- a/crates/uv-resolver/src/lock/export/cyclonedx_json.rs +++ b/crates/uv-resolver/src/lock/export/cyclonedx_json.rs @@ -17,7 +17,7 @@ use uv_configuration::{ use uv_fs::PortablePath; use uv_normalize::PackageName; use uv_pep508::MarkerTree; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_warnings::warn_user; use crate::lock::export::{ExportableRequirement, ExportableRequirements}; @@ -263,10 +263,10 @@ pub fn from_lock<'lock>( preview: Preview, all_packages: bool, ) -> Result { - if !preview.is_enabled(PreviewFeatures::SBOM_EXPORT) { + if !preview.is_enabled(PreviewFeature::SbomExport) { warn_user!( "`uv export --format=cyclonedx1.5` is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::SBOM_EXPORT + PreviewFeature::SbomExport ); } diff --git a/crates/uv/src/commands/auth/helper.rs b/crates/uv/src/commands/auth/helper.rs index f20e0a2d099be..5cfa5555b3a1d 100644 --- a/crates/uv/src/commands/auth/helper.rs +++ b/crates/uv/src/commands/auth/helper.rs @@ -8,7 +8,7 @@ use tracing::debug; use uv_auth::{AuthBackend, Credentials, DEFAULT_TOLERANCE_SECS, PyxTokenStore}; use uv_client::BaseClientBuilder; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_redacted::DisplaySafeUrl; use uv_warnings::warn_user; @@ -123,10 +123,10 @@ pub(crate) async fn helper( preview: Preview, printer: Printer, ) -> Result { - if !preview.is_enabled(PreviewFeatures::AUTH_HELPER) { + if !preview.is_enabled(PreviewFeature::AuthHelper) { warn_user!( "The `uv auth helper` command is experimental and may change without warning. Pass `--preview-features {}` to disable this warning", - PreviewFeatures::AUTH_HELPER + PreviewFeature::AuthHelper ); } diff --git a/crates/uv/src/commands/cache_size.rs b/crates/uv/src/commands/cache_size.rs index 46ef3216db8cd..387aae8e681bf 100644 --- a/crates/uv/src/commands/cache_size.rs +++ b/crates/uv/src/commands/cache_size.rs @@ -6,7 +6,7 @@ use diskus::DiskUsage; use crate::commands::{ExitStatus, human_readable_bytes}; use crate::printer::Printer; use uv_cache::Cache; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_warnings::warn_user; /// Display the total size of the cache. @@ -16,10 +16,10 @@ pub(crate) fn cache_size( printer: Printer, preview: Preview, ) -> Result { - if !preview.is_enabled(PreviewFeatures::CACHE_SIZE) { + if !preview.is_enabled(PreviewFeature::CacheSize) { warn_user!( "`uv cache size` is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::CACHE_SIZE + PreviewFeature::CacheSize ); } diff --git a/crates/uv/src/commands/pip/compile.rs b/crates/uv/src/commands/pip/compile.rs index 5c7900c10e036..f1b1d843c5349 100644 --- a/crates/uv/src/commands/pip/compile.rs +++ b/crates/uv/src/commands/pip/compile.rs @@ -29,7 +29,7 @@ use uv_fs::{CWD, Simplified}; use uv_git::ResolvedRepositoryReference; use uv_install_wheel::LinkMode; use uv_normalize::PackageName; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_pypi_types::{Conflicts, SupportedEnvironments}; use uv_python::{ EnvironmentPreference, PythonDownloads, PythonEnvironment, PythonInstallation, @@ -123,12 +123,12 @@ pub(crate) async fn pip_compile( printer: Printer, preview: Preview, ) -> Result { - if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES) + if !preview.is_enabled(PreviewFeature::ExtraBuildDependencies) && !extra_build_dependencies.is_empty() { warn_user_once!( "The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::EXTRA_BUILD_DEPENDENCIES + PreviewFeature::ExtraBuildDependencies ); } diff --git a/crates/uv/src/commands/pip/install.rs b/crates/uv/src/commands/pip/install.rs index 297e72fe90e33..7cba0f1909ef2 100644 --- a/crates/uv/src/commands/pip/install.rs +++ b/crates/uv/src/commands/pip/install.rs @@ -23,7 +23,7 @@ use uv_fs::Simplified; use uv_install_wheel::LinkMode; use uv_installer::{InstallationStrategy, SatisfiesResult, SitePackages}; use uv_normalize::{DefaultExtras, DefaultGroups, PackageName}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_pypi_types::Conflicts; use uv_python::{ EnvironmentPreference, Prefix, PythonDownloads, PythonEnvironment, PythonInstallation, @@ -106,12 +106,12 @@ pub(crate) async fn pip_install( ) -> anyhow::Result { let start = std::time::Instant::now(); - if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES) + if !preview.is_enabled(PreviewFeature::ExtraBuildDependencies) && !extra_build_dependencies.is_empty() { warn_user_once!( "The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::EXTRA_BUILD_DEPENDENCIES + PreviewFeature::ExtraBuildDependencies ); } @@ -146,10 +146,10 @@ pub(crate) async fn pip_install( .await?; if pylock.is_some() { - if !preview.is_enabled(PreviewFeatures::PYLOCK) { + if !preview.is_enabled(PreviewFeature::Pylock) { warn_user!( "The `--pylock` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::PYLOCK + PreviewFeature::Pylock ); } } diff --git a/crates/uv/src/commands/pip/sync.rs b/crates/uv/src/commands/pip/sync.rs index 64d7d75dbc508..c8fc45e018e12 100644 --- a/crates/uv/src/commands/pip/sync.rs +++ b/crates/uv/src/commands/pip/sync.rs @@ -22,7 +22,7 @@ use uv_fs::Simplified; use uv_install_wheel::LinkMode; use uv_installer::{InstallationStrategy, SitePackages}; use uv_normalize::{DefaultExtras, DefaultGroups}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_pypi_types::Conflicts; use uv_python::{ EnvironmentPreference, Prefix, PythonDownloads, PythonEnvironment, PythonInstallation, @@ -93,12 +93,12 @@ pub(crate) async fn pip_sync( printer: Printer, preview: Preview, ) -> Result { - if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES) + if !preview.is_enabled(PreviewFeature::ExtraBuildDependencies) && !extra_build_dependencies.is_empty() { warn_user_once!( "The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::EXTRA_BUILD_DEPENDENCIES + PreviewFeature::ExtraBuildDependencies ); } @@ -141,10 +141,10 @@ pub(crate) async fn pip_sync( .await?; if pylock.is_some() { - if !preview.is_enabled(PreviewFeatures::PYLOCK) { + if !preview.is_enabled(PreviewFeature::Pylock) { warn_user!( "The `--pylock` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::PYLOCK + PreviewFeature::Pylock ); } } diff --git a/crates/uv/src/commands/project/add.rs b/crates/uv/src/commands/project/add.rs index fcb100a32325c..3c0bf54763223 100644 --- a/crates/uv/src/commands/project/add.rs +++ b/crates/uv/src/commands/project/add.rs @@ -29,7 +29,7 @@ use uv_fs::{LockedFile, LockedFileError, Simplified}; use uv_git::GIT_STORE; use uv_normalize::{DEV_DEPENDENCIES, DefaultExtras, DefaultGroups, ExtraName, PackageName}; use uv_pep508::{MarkerTree, VersionOrUrl}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_python::{Interpreter, PythonDownloads, PythonEnvironment, PythonPreference, PythonRequest}; use uv_redacted::DisplaySafeUrl; use uv_requirements::{NamedRequirementsResolver, RequirementsSource, RequirementsSpecification}; @@ -103,19 +103,19 @@ pub(crate) async fn add( printer: Printer, preview: Preview, ) -> Result { - if bounds.is_some() && !preview.is_enabled(PreviewFeatures::ADD_BOUNDS) { + if bounds.is_some() && !preview.is_enabled(PreviewFeature::AddBounds) { warn_user_once!( "The `bounds` option is in preview and may change in any future release. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::ADD_BOUNDS + PreviewFeature::AddBounds ); } - if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES) + if !preview.is_enabled(PreviewFeature::ExtraBuildDependencies) && !settings.resolver.extra_build_dependencies.is_empty() { warn_user_once!( "The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::EXTRA_BUILD_DEPENDENCIES + PreviewFeature::ExtraBuildDependencies ); } diff --git a/crates/uv/src/commands/project/format.rs b/crates/uv/src/commands/project/format.rs index 312b3531f84dd..687f67f5bdb92 100644 --- a/crates/uv/src/commands/project/format.rs +++ b/crates/uv/src/commands/project/format.rs @@ -8,7 +8,7 @@ use uv_bin_install::{Binary, bin_install}; use uv_cache::Cache; use uv_client::BaseClientBuilder; use uv_pep440::Version; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_warnings::warn_user; use uv_workspace::{DiscoveryOptions, VirtualProject, WorkspaceCache, WorkspaceError}; @@ -31,10 +31,10 @@ pub(crate) async fn format( no_project: bool, ) -> Result { // Check if the format feature is in preview - if !preview.is_enabled(PreviewFeatures::FORMAT) { + if !preview.is_enabled(PreviewFeature::Format) { warn_user!( "`uv format` is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::FORMAT + PreviewFeature::Format ); } diff --git a/crates/uv/src/commands/project/lock.rs b/crates/uv/src/commands/project/lock.rs index b4b65bd52238d..210a625ddeb56 100644 --- a/crates/uv/src/commands/project/lock.rs +++ b/crates/uv/src/commands/project/lock.rs @@ -25,7 +25,7 @@ use uv_git::ResolvedRepositoryReference; use uv_git_types::GitOid; use uv_normalize::{GroupName, PackageName}; use uv_pep440::Version; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_pypi_types::{ConflictKind, Conflicts, SupportedEnvironments}; use uv_python::{Interpreter, PythonDownloads, PythonEnvironment, PythonPreference, PythonRequest}; use uv_requirements::ExtrasResolver; @@ -472,12 +472,12 @@ async fn do_lock( torch_backend: _, } = settings; - if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES) + if !preview.is_enabled(PreviewFeature::ExtraBuildDependencies) && !extra_build_dependencies.is_empty() { warn_user_once!( "The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::EXTRA_BUILD_DEPENDENCIES + PreviewFeature::ExtraBuildDependencies ); } @@ -542,7 +542,7 @@ async fn do_lock( } // Check if any conflicts contain project-level conflicts - if !preview.is_enabled(PreviewFeatures::PACKAGE_CONFLICTS) + if !preview.is_enabled(PreviewFeature::PackageConflicts) && conflicts.iter().any(|set| { set.iter() .any(|item| matches!(item.kind(), ConflictKind::Project)) @@ -550,7 +550,7 @@ async fn do_lock( { warn_user_once!( "Declaring conflicts for packages (`package = ...`) is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::PACKAGE_CONFLICTS + PreviewFeature::PackageConflicts ); } diff --git a/crates/uv/src/commands/project/mod.rs b/crates/uv/src/commands/project/mod.rs index 4f831abf70396..fc706b2436c32 100644 --- a/crates/uv/src/commands/project/mod.rs +++ b/crates/uv/src/commands/project/mod.rs @@ -27,7 +27,7 @@ use uv_installer::{InstallationStrategy, SatisfiesResult, SitePackages}; use uv_normalize::{DEV_DEPENDENCIES, DefaultGroups, ExtraName, GroupName, PackageName}; use uv_pep440::{TildeVersionSpecifier, Version, VersionSpecifiers}; use uv_pep508::MarkerTreeContents; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_pypi_types::{ConflictItem, ConflictKind, ConflictSet, Conflicts}; use uv_python::{ EnvironmentPreference, Interpreter, InvalidEnvironmentKind, PythonDownloads, PythonEnvironment, @@ -1351,7 +1351,7 @@ impl ProjectEnvironment { }) .ok(); - let upgradeable = preview.is_enabled(PreviewFeatures::PYTHON_UPGRADE) + let upgradeable = preview.is_enabled(PreviewFeature::PythonUpgrade) && python .as_ref() .is_none_or(|request| !request.includes_patch()); diff --git a/crates/uv/src/commands/project/run.rs b/crates/uv/src/commands/project/run.rs index 233d437ce69b7..9561ca92a6307 100644 --- a/crates/uv/src/commands/project/run.rs +++ b/crates/uv/src/commands/project/run.rs @@ -28,7 +28,7 @@ use uv_fs::which::is_executable; use uv_fs::{PythonExt, Simplified, create_symlink}; use uv_installer::{InstallationStrategy, SatisfiesResult, SitePackages}; use uv_normalize::{DefaultExtras, DefaultGroups, PackageName}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_python::{ EnvironmentPreference, Interpreter, PyVenvConfiguration, PythonDownloads, PythonEnvironment, PythonInstallation, PythonPreference, PythonRequest, PythonVersionFile, @@ -549,7 +549,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl // When running a target with the preview flag enabled, discover the workspace starting // from the target's directory rather than the current working directory. let discovery_dir: Cow<'_, Path> = - if preview.is_enabled(PreviewFeatures::TARGET_WORKSPACE_DISCOVERY) { + if preview.is_enabled(PreviewFeature::TargetWorkspaceDiscovery) { if let Some(dir) = command.as_ref().and_then(RunCommand::script_dir) { Cow::Owned(std::path::absolute(dir)?) } else { diff --git a/crates/uv/src/commands/project/sync.rs b/crates/uv/src/commands/project/sync.rs index d6aa1ae90d8dd..07f674af1d13f 100644 --- a/crates/uv/src/commands/project/sync.rs +++ b/crates/uv/src/commands/project/sync.rs @@ -25,7 +25,7 @@ use uv_fs::{PortablePathBuf, Simplified}; use uv_installer::{InstallationStrategy, SitePackages}; use uv_normalize::{DefaultExtras, DefaultGroups, PackageName}; use uv_pep508::{MarkerTree, VersionOrUrl}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_pypi_types::{ParsedArchiveUrl, ParsedGitUrl, ParsedUrl}; use uv_python::{PythonDownloads, PythonEnvironment, PythonPreference, PythonRequest}; use uv_resolver::{FlatIndex, ForkStrategy, Installable, Lock, PrereleaseMode, ResolutionMode}; @@ -85,11 +85,10 @@ pub(crate) async fn sync( preview: Preview, output_format: SyncFormat, ) -> Result { - if preview.is_enabled(PreviewFeatures::JSON_OUTPUT) && matches!(output_format, SyncFormat::Json) - { + if preview.is_enabled(PreviewFeature::JsonOutput) && matches!(output_format, SyncFormat::Json) { warn_user!( "The `--output-format json` option is experimental and the schema may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::JSON_OUTPUT + PreviewFeature::JsonOutput ); } @@ -640,12 +639,12 @@ pub(super) async fn do_sync( sources, } = settings; - if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES) + if !preview.is_enabled(PreviewFeature::ExtraBuildDependencies) && !extra_build_dependencies.is_empty() { warn_user_once!( "The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::EXTRA_BUILD_DEPENDENCIES + PreviewFeature::ExtraBuildDependencies ); } diff --git a/crates/uv/src/commands/publish.rs b/crates/uv/src/commands/publish.rs index 759d794a721e6..31a4ad7cf0c1a 100644 --- a/crates/uv/src/commands/publish.rs +++ b/crates/uv/src/commands/publish.rs @@ -13,7 +13,7 @@ use uv_client::{ }; use uv_configuration::{KeyringProviderType, TrustedPublishing}; use uv_distribution_types::{IndexCapabilities, IndexLocations, IndexUrl}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_publish::{ CheckUrlClient, FormMetadata, PublishError, TrustedPublishResult, check_trusted_publishing, group_files_for_publishing, upload, upload_two_phase, @@ -49,11 +49,11 @@ pub(crate) async fn publish( bail!("Unable to publish files in offline mode"); } - if direct && !preview.is_enabled(PreviewFeatures::DIRECT_PUBLISH) { + if direct && !preview.is_enabled(PreviewFeature::DirectPublish) { warn_user_once!( "The `--direct` option is experimental and may change without warning. \ Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::DIRECT_PUBLISH + PreviewFeature::DirectPublish ); } diff --git a/crates/uv/src/commands/python/install.rs b/crates/uv/src/commands/python/install.rs index 2d1999c47fd85..e2e4049a97a22 100644 --- a/crates/uv/src/commands/python/install.rs +++ b/crates/uv/src/commands/python/install.rs @@ -19,7 +19,7 @@ use uv_client::BaseClientBuilder; use uv_configuration::Concurrency; use uv_fs::Simplified; use uv_platform::{Arch, Libc}; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_python::downloads::{ self, ArchRequest, DownloadResult, ManagedPythonDownload, ManagedPythonDownloadList, PythonDownloadRequest, @@ -311,18 +311,18 @@ async fn perform_install( // `--default` is used. It's not clear how this overlaps with a global Python pin, but I'd be // surprised if `uv python find` returned the "newest" Python version rather than the one I just // installed with the `--default` flag. - if default && !preview.is_enabled(PreviewFeatures::PYTHON_INSTALL_DEFAULT) { + if default && !preview.is_enabled(PreviewFeature::PythonInstallDefault) { warn_user!( "The `--default` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning", - PreviewFeatures::PYTHON_INSTALL_DEFAULT + PreviewFeature::PythonInstallDefault ); } if let PythonUpgrade::Enabled(source @ PythonUpgradeSource::Upgrade) = upgrade { - if !preview.is_enabled(PreviewFeatures::PYTHON_UPGRADE) { + if !preview.is_enabled(PreviewFeature::PythonUpgrade) { warn_user!( "`{source}` is experimental and may change without warning. Pass `--preview-features {}` to disable this warning", - PreviewFeatures::PYTHON_UPGRADE + PreviewFeature::PythonUpgrade ); } } @@ -972,8 +972,8 @@ fn create_bin_links( // TODO(zanieb): We want more feedback on the `is_default_install` behavior before stabilizing // it. In particular, it may be confusing because it does not apply when versions are loaded // from a `.python-version` file. - let should_create_default_links = default - || (is_default_install && preview.is_enabled(PreviewFeatures::PYTHON_INSTALL_DEFAULT)); + let should_create_default_links = + default || (is_default_install && preview.is_enabled(PreviewFeature::PythonInstallDefault)); let targets = if should_create_default_links { vec![ diff --git a/crates/uv/src/commands/venv.rs b/crates/uv/src/commands/venv.rs index 9617dd8b0f289..aa6f734e452b1 100644 --- a/crates/uv/src/commands/venv.rs +++ b/crates/uv/src/commands/venv.rs @@ -21,7 +21,7 @@ use uv_distribution_types::{ use uv_fs::Simplified; use uv_install_wheel::LinkMode; use uv_normalize::DefaultGroups; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_python::{ EnvironmentPreference, PythonDownloads, PythonInstallation, PythonPreference, PythonRequest, }; @@ -190,7 +190,7 @@ pub(crate) async fn venv( path.user_display().cyan() )?; - let upgradeable = preview.is_enabled(PreviewFeatures::PYTHON_UPGRADE) + let upgradeable = preview.is_enabled(PreviewFeature::PythonUpgrade) && python_request .as_ref() .is_none_or(|request| !request.includes_patch()); diff --git a/crates/uv/src/commands/workspace/dir.rs b/crates/uv/src/commands/workspace/dir.rs index 23cf35b08f0a7..eb3f0527f1d83 100644 --- a/crates/uv/src/commands/workspace/dir.rs +++ b/crates/uv/src/commands/workspace/dir.rs @@ -6,7 +6,7 @@ use anyhow::{Result, bail}; use owo_colors::OwoColorize; use uv_fs::Simplified; use uv_normalize::PackageName; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_warnings::warn_user; use uv_workspace::{DiscoveryOptions, Workspace, WorkspaceCache}; @@ -20,10 +20,10 @@ pub(crate) async fn dir( preview: Preview, printer: Printer, ) -> Result { - if !preview.is_enabled(PreviewFeatures::WORKSPACE_DIR) { + if !preview.is_enabled(PreviewFeature::WorkspaceDir) { warn_user!( "The `uv workspace dir` command is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::WORKSPACE_DIR + PreviewFeature::WorkspaceDir ); } diff --git a/crates/uv/src/commands/workspace/list.rs b/crates/uv/src/commands/workspace/list.rs index 5ad0749844635..24c7a63537610 100644 --- a/crates/uv/src/commands/workspace/list.rs +++ b/crates/uv/src/commands/workspace/list.rs @@ -5,7 +5,7 @@ use anyhow::Result; use owo_colors::OwoColorize; use uv_fs::Simplified; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_warnings::warn_user; use uv_workspace::{DiscoveryOptions, Workspace, WorkspaceCache}; @@ -19,10 +19,10 @@ pub(crate) async fn list( preview: Preview, printer: Printer, ) -> Result { - if !preview.is_enabled(PreviewFeatures::WORKSPACE_LIST) { + if !preview.is_enabled(PreviewFeature::WorkspaceList) { warn_user!( "The `uv workspace list` command is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::WORKSPACE_LIST + PreviewFeature::WorkspaceList ); } diff --git a/crates/uv/src/commands/workspace/metadata.rs b/crates/uv/src/commands/workspace/metadata.rs index 9fb9e44e13a1a..bcbd94acc12f1 100644 --- a/crates/uv/src/commands/workspace/metadata.rs +++ b/crates/uv/src/commands/workspace/metadata.rs @@ -6,7 +6,7 @@ use serde::Serialize; use uv_fs::PortablePathBuf; use uv_normalize::PackageName; -use uv_preview::{Preview, PreviewFeatures}; +use uv_preview::{Preview, PreviewFeature}; use uv_warnings::warn_user; use uv_workspace::{DiscoveryOptions, Workspace, WorkspaceCache}; @@ -55,10 +55,10 @@ pub(crate) async fn metadata( preview: Preview, printer: Printer, ) -> Result { - if !preview.is_enabled(PreviewFeatures::WORKSPACE_METADATA) { + if !preview.is_enabled(PreviewFeature::WorkspaceMetadata) { warn_user!( "The `uv workspace metadata` command is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.", - PreviewFeatures::WORKSPACE_METADATA + PreviewFeature::WorkspaceMetadata ); } diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index b2291b9a94e95..cdd8b3f1b494c 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -40,7 +40,7 @@ use uv_fs::{CWD, Simplified}; #[cfg(feature = "self-update")] use uv_pep440::release_specifiers_to_ranges; use uv_pep508::VersionOrUrl; -use uv_preview::PreviewFeatures; +use uv_preview::PreviewFeature; use uv_pypi_types::{ParsedDirectoryUrl, ParsedUrl}; use uv_python::PythonRequest; use uv_requirements::{GroupsSpecification, RequirementsSource}; @@ -340,7 +340,7 @@ async fn run(mut cli: Cli) -> Result { // Adjust open file limits on Unix if the preview feature is enabled. #[cfg(unix)] - if globals.preview.is_enabled(PreviewFeatures::ADJUST_ULIMIT) { + if globals.preview.is_enabled(PreviewFeature::AdjustUlimit) { match uv_unix::adjust_open_file_limit() { Ok(_) | Err(uv_unix::OpenFileLimitError::AlreadySufficient { .. }) => {} // TODO(zanieb): When moving out of preview, consider changing this to a log instead of @@ -1962,10 +1962,7 @@ async fn run_project( // The `--project` arg is being deprecated for `init` with a warning now and an error in preview. if explicit_project { - if globals - .preview - .is_enabled(PreviewFeatures::INIT_PROJECT_FLAG) - { + if globals.preview.is_enabled(PreviewFeature::InitProjectFlag) { bail!( "The `--project` option cannot be used in `uv init`. {}", if args.path.is_some() { diff --git a/crates/uv/tests/it/show_settings.rs b/crates/uv/tests/it/show_settings.rs index 2727d644133c2..116601ac3e0c6 100644 --- a/crates/uv/tests/it/show_settings.rs +++ b/crates/uv/tests/it/show_settings.rs @@ -76,9 +76,9 @@ fn resolve_uv_toml() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -283,9 +283,9 @@ fn resolve_uv_toml() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -491,9 +491,9 @@ fn resolve_uv_toml() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -731,9 +731,9 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -940,9 +940,9 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -1125,9 +1125,9 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -1359,9 +1359,9 @@ fn resolve_index_url() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -1601,9 +1601,9 @@ fn resolve_index_url() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -1901,9 +1901,9 @@ fn resolve_find_links() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -2132,9 +2132,9 @@ fn resolve_top_level() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -2322,9 +2322,9 @@ fn resolve_top_level() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -2562,9 +2562,9 @@ fn resolve_top_level() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -2825,9 +2825,9 @@ fn resolve_user_configuration() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -3005,9 +3005,9 @@ fn resolve_user_configuration() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -3185,9 +3185,9 @@ fn resolve_user_configuration() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -3367,9 +3367,9 @@ fn resolve_user_configuration() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -3568,9 +3568,9 @@ fn resolve_tool() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -3764,9 +3764,9 @@ fn resolve_poetry_toml() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -3978,9 +3978,9 @@ fn resolve_both() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -4231,9 +4231,9 @@ fn resolve_both_special_fields() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -4563,9 +4563,9 @@ fn resolve_config_file() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -4870,9 +4870,9 @@ fn resolve_skip_empty() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -5053,9 +5053,9 @@ fn resolve_skip_empty() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -5255,9 +5255,9 @@ fn allow_insecure_host() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -5449,9 +5449,9 @@ fn index_priority() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -5691,9 +5691,9 @@ fn index_priority() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -5939,9 +5939,9 @@ fn index_priority() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -6182,9 +6182,9 @@ fn index_priority() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -6432,9 +6432,9 @@ fn index_priority() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -6675,9 +6675,9 @@ fn index_priority() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -6931,9 +6931,9 @@ fn verify_hashes() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -7104,9 +7104,9 @@ fn verify_hashes() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -7275,9 +7275,9 @@ fn verify_hashes() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -7448,9 +7448,9 @@ fn verify_hashes() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -7619,9 +7619,9 @@ fn verify_hashes() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -7791,9 +7791,9 @@ fn verify_hashes() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -7978,9 +7978,10 @@ fn preview_features() { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE | JSON_OUTPUT | PYLOCK | ADD_BOUNDS | PACKAGE_CONFLICTS | EXTRA_BUILD_DEPENDENCIES | DETECT_MODULE_CONFLICTS | FORMAT | NATIVE_AUTH | S3_ENDPOINT | CACHE_SIZE | INIT_PROJECT_FLAG | WORKSPACE_METADATA | WORKSPACE_DIR | WORKSPACE_LIST | SBOM_EXPORT | AUTH_HELPER | DIRECT_PUBLISH | TARGET_WORKSPACE_DISCOVERY | METADATA_JSON | GCS_ENDPOINT | ADJUST_ULIMIT, - ), + flags: BitFlags { + bits: 0b11111111111111111111111, + flags: PythonInstallDefault | PythonUpgrade | JsonOutput | Pylock | AddBounds | PackageConflicts | ExtraBuildDependencies | DetectModuleConflicts | Format | NativeAuth | S3Endpoint | CacheSize | InitProjectFlag | WorkspaceMetadata | WorkspaceDir | WorkspaceList | SbomExport | AuthHelper | DirectPublish | TargetWorkspaceDiscovery | MetadataJson | GcsEndpoint | AdjustUlimit, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -8097,9 +8098,9 @@ fn preview_features() { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -8216,9 +8217,10 @@ fn preview_features() { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE | JSON_OUTPUT | PYLOCK | ADD_BOUNDS | PACKAGE_CONFLICTS | EXTRA_BUILD_DEPENDENCIES | DETECT_MODULE_CONFLICTS | FORMAT | NATIVE_AUTH | S3_ENDPOINT | CACHE_SIZE | INIT_PROJECT_FLAG | WORKSPACE_METADATA | WORKSPACE_DIR | WORKSPACE_LIST | SBOM_EXPORT | AUTH_HELPER | DIRECT_PUBLISH | TARGET_WORKSPACE_DISCOVERY | METADATA_JSON | GCS_ENDPOINT | ADJUST_ULIMIT, - ), + flags: BitFlags { + bits: 0b11111111111111111111111, + flags: PythonInstallDefault | PythonUpgrade | JsonOutput | Pylock | AddBounds | PackageConflicts | ExtraBuildDependencies | DetectModuleConflicts | Format | NativeAuth | S3Endpoint | CacheSize | InitProjectFlag | WorkspaceMetadata | WorkspaceDir | WorkspaceList | SbomExport | AuthHelper | DirectPublish | TargetWorkspaceDiscovery | MetadataJson | GcsEndpoint | AdjustUlimit, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -8335,9 +8337,10 @@ fn preview_features() { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE, - ), + flags: BitFlags { + bits: 0b11, + flags: PythonInstallDefault | PythonUpgrade, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -8454,9 +8457,10 @@ fn preview_features() { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE, - ), + flags: BitFlags { + bits: 0b11, + flags: PythonInstallDefault | PythonUpgrade, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -8575,9 +8579,9 @@ fn preview_features() { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -8715,9 +8719,9 @@ fn upgrade_pip_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -8896,9 +8900,9 @@ fn upgrade_pip_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -9100,9 +9104,9 @@ fn upgrade_pip_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -9279,9 +9283,9 @@ fn upgrade_pip_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -9452,9 +9456,9 @@ fn upgrade_pip_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -9626,9 +9630,9 @@ fn upgrade_pip_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -9865,9 +9869,9 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -9989,9 +9993,9 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -10136,9 +10140,9 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -10258,9 +10262,9 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -10370,9 +10374,9 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -10483,9 +10487,9 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -10660,9 +10664,9 @@ fn build_isolation_override() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic, @@ -10836,9 +10840,9 @@ fn build_isolation_override() -> anyhow::Result<()> { }, show_settings: true, preview: Preview { - flags: PreviewFeatures( - 0x0, - ), + flags: BitFlags { + bits: 0b0, + }, }, python_preference: Managed, python_downloads: Automatic,