Added config file settings validation for preview features#17202
Added config file settings validation for preview features#17202j-helland wants to merge 9 commits into
Conversation
Preview features are specified as a list of strings in TOML, which parse to PreviewFeatures values. CLI arguments like --preview and --no-preview take precedence over config values. --preview-features combines with config values.
…e fields * Instead of merging commandline `--preview-features` with config file `preview-features`, now the commandline arguments take precedence. This matches the semantics of how uv handles other commandline arguments. * Removed unnecessary `PreviewFeaturesMode` type. * Fixed bug with `PreviewFeatures` serde serializer that produced a list of lists instead of a flat list as expected.
| pub(crate) trait Validator<Context = (), Err = ValidationError> { | ||
| fn validate(&self, ctx: &Context) -> Result<(), Err>; | ||
| } |
There was a problem hiding this comment.
This trait might be overkill. If we think that there will be lots of additional validation rules in the future, something like this makes sense. If not, simplifying to something like validate_uv_toml would be better.
YAGNI?
| tracing::debug!("Found user configuration in: `{}`", file.display()); | ||
| options.validate(&Context { path: &file })?; |
There was a problem hiding this comment.
I didn't consolidate validate_uv_toml into the validator trait impl because it actually doesn't get called in the pyproject.toml branch and tests would fail if it was called there.
ab5f1cd to
b24e193
Compare
Specifically, disallow specifying both `preview` and `preview-features` in the config files. The implementation is intended to be extensible, should more validation rules be needed in the future.
b24e193 to
259a9d4
Compare
|
For this kind of validation, I feel like having to remember to validate the options everywhere is a bit error prone. Since all sources of this data will need this validation, it's best to implement it with a custom In fact, the best way to do this is to just repurpose the impl<'de> Deserialize<'de> for Options {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let wire = OptionsWire::deserialize(deserializer)?;
if wire.preview_features.is_some() && wire.preview.is_some() {
return Err(serde::de::Error::custom(
"Cannot specify both `preview` and `preview-features`.",
));
}
let OptionsWire {
required_version,
native_tls,
...See also #16452 (comment). |
Nice, thanks for the pointer! Centralizing into the deserializer is good. It would make the most sense to me, then, to consolidate what you suggest into the original PR #16452 once the design there is clarified. I can do it in this PR if you all would prefer, though. |
Stacked on #16452
Summary
Note
For reviewers: see the last commit
Per discussion #16452 (comment), it was determined that we need to have additional config validation for the
previewandpreview-featuresfields.This is a sketch of how we might approach that via a
Validatortrait implemented forOptionsandGlobalOptions.Test Plan
New and existing automated tests.
Example