Skip to content

Commit a42a284

Browse files
authored
Make warnings about masked [tool.uv] fields more precise (#14325)
This is the second half of #14308
1 parent dbe6a21 commit a42a284

File tree

2 files changed

+482
-5
lines changed

2 files changed

+482
-5
lines changed

crates/uv-settings/src/lib.rs

Lines changed: 250 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,9 @@ impl FilesystemOptions {
120120
.ok()
121121
.and_then(|content| toml::from_str::<PyProjectToml>(&content).ok())
122122
{
123-
if pyproject.tool.is_some_and(|tool| tool.uv.is_some()) {
124-
warn_user!(
125-
"Found both a `uv.toml` file and a `[tool.uv]` section in an adjacent `pyproject.toml`. The `[tool.uv]` section will be ignored in favor of the `uv.toml` file."
126-
);
123+
if let Some(options) = pyproject.tool.as_ref().and_then(|tool| tool.uv.as_ref())
124+
{
125+
warn_uv_toml_masked_fields(options);
127126
}
128127
}
129128

@@ -269,6 +268,253 @@ fn validate_uv_toml(path: &Path, options: &Options) -> Result<(), Error> {
269268
Ok(())
270269
}
271270

271+
/// Validate that an [`Options`] contains no fields that `uv.toml` would mask
272+
///
273+
/// This is essentially the inverse of [`validated_uv_toml`][].
274+
fn warn_uv_toml_masked_fields(options: &Options) {
275+
let Options {
276+
globals:
277+
GlobalOptions {
278+
required_version,
279+
native_tls,
280+
offline,
281+
no_cache,
282+
cache_dir,
283+
preview,
284+
python_preference,
285+
python_downloads,
286+
concurrent_downloads,
287+
concurrent_builds,
288+
concurrent_installs,
289+
allow_insecure_host,
290+
},
291+
top_level:
292+
ResolverInstallerOptions {
293+
index,
294+
index_url,
295+
extra_index_url,
296+
no_index,
297+
find_links,
298+
index_strategy,
299+
keyring_provider,
300+
resolution,
301+
prerelease,
302+
fork_strategy,
303+
dependency_metadata,
304+
config_settings,
305+
no_build_isolation,
306+
no_build_isolation_package,
307+
exclude_newer,
308+
link_mode,
309+
compile_bytecode,
310+
no_sources,
311+
upgrade,
312+
upgrade_package,
313+
reinstall,
314+
reinstall_package,
315+
no_build,
316+
no_build_package,
317+
no_binary,
318+
no_binary_package,
319+
},
320+
install_mirrors:
321+
PythonInstallMirrors {
322+
python_install_mirror,
323+
pypy_install_mirror,
324+
python_downloads_json_url,
325+
},
326+
publish:
327+
PublishOptions {
328+
publish_url,
329+
trusted_publishing,
330+
check_url,
331+
},
332+
add: AddOptions { add_bounds },
333+
pip,
334+
cache_keys,
335+
override_dependencies,
336+
constraint_dependencies,
337+
build_constraint_dependencies,
338+
environments,
339+
required_environments,
340+
conflicts: _,
341+
workspace: _,
342+
sources: _,
343+
dev_dependencies: _,
344+
default_groups: _,
345+
dependency_groups: _,
346+
managed: _,
347+
package: _,
348+
build_backend: _,
349+
} = options;
350+
351+
let mut masked_fields = vec![];
352+
353+
if required_version.is_some() {
354+
masked_fields.push("required-version");
355+
}
356+
if native_tls.is_some() {
357+
masked_fields.push("native-tls");
358+
}
359+
if offline.is_some() {
360+
masked_fields.push("offline");
361+
}
362+
if no_cache.is_some() {
363+
masked_fields.push("no-cache");
364+
}
365+
if cache_dir.is_some() {
366+
masked_fields.push("cache-dir");
367+
}
368+
if preview.is_some() {
369+
masked_fields.push("preview");
370+
}
371+
if python_preference.is_some() {
372+
masked_fields.push("python-preference");
373+
}
374+
if python_downloads.is_some() {
375+
masked_fields.push("python-downloads");
376+
}
377+
if concurrent_downloads.is_some() {
378+
masked_fields.push("concurrent-downloads");
379+
}
380+
if concurrent_builds.is_some() {
381+
masked_fields.push("concurrent-builds");
382+
}
383+
if concurrent_installs.is_some() {
384+
masked_fields.push("concurrent-installs");
385+
}
386+
if allow_insecure_host.is_some() {
387+
masked_fields.push("allow-insecure-host");
388+
}
389+
if index.is_some() {
390+
masked_fields.push("index");
391+
}
392+
if index_url.is_some() {
393+
masked_fields.push("index-url");
394+
}
395+
if extra_index_url.is_some() {
396+
masked_fields.push("extra-index-url");
397+
}
398+
if no_index.is_some() {
399+
masked_fields.push("no-index");
400+
}
401+
if find_links.is_some() {
402+
masked_fields.push("find-links");
403+
}
404+
if index_strategy.is_some() {
405+
masked_fields.push("index-strategy");
406+
}
407+
if keyring_provider.is_some() {
408+
masked_fields.push("keyring-provider");
409+
}
410+
if resolution.is_some() {
411+
masked_fields.push("resolution");
412+
}
413+
if prerelease.is_some() {
414+
masked_fields.push("prerelease");
415+
}
416+
if fork_strategy.is_some() {
417+
masked_fields.push("fork-strategy");
418+
}
419+
if dependency_metadata.is_some() {
420+
masked_fields.push("dependency-metadata");
421+
}
422+
if config_settings.is_some() {
423+
masked_fields.push("config-settings");
424+
}
425+
if no_build_isolation.is_some() {
426+
masked_fields.push("no-build-isolation");
427+
}
428+
if no_build_isolation_package.is_some() {
429+
masked_fields.push("no-build-isolation-package");
430+
}
431+
if exclude_newer.is_some() {
432+
masked_fields.push("exclude-newer");
433+
}
434+
if link_mode.is_some() {
435+
masked_fields.push("link-mode");
436+
}
437+
if compile_bytecode.is_some() {
438+
masked_fields.push("compile-bytecode");
439+
}
440+
if no_sources.is_some() {
441+
masked_fields.push("no-sources");
442+
}
443+
if upgrade.is_some() {
444+
masked_fields.push("upgrade");
445+
}
446+
if upgrade_package.is_some() {
447+
masked_fields.push("upgrade-package");
448+
}
449+
if reinstall.is_some() {
450+
masked_fields.push("reinstall");
451+
}
452+
if reinstall_package.is_some() {
453+
masked_fields.push("reinstall-package");
454+
}
455+
if no_build.is_some() {
456+
masked_fields.push("no-build");
457+
}
458+
if no_build_package.is_some() {
459+
masked_fields.push("no-build-package");
460+
}
461+
if no_binary.is_some() {
462+
masked_fields.push("no-binary");
463+
}
464+
if no_binary_package.is_some() {
465+
masked_fields.push("no-binary-package");
466+
}
467+
if python_install_mirror.is_some() {
468+
masked_fields.push("python-install-mirror");
469+
}
470+
if pypy_install_mirror.is_some() {
471+
masked_fields.push("pypy-install-mirror");
472+
}
473+
if python_downloads_json_url.is_some() {
474+
masked_fields.push("python-downloads-json-url");
475+
}
476+
if publish_url.is_some() {
477+
masked_fields.push("publish-url");
478+
}
479+
if trusted_publishing.is_some() {
480+
masked_fields.push("trusted-publishing");
481+
}
482+
if check_url.is_some() {
483+
masked_fields.push("check-url");
484+
}
485+
if add_bounds.is_some() {
486+
masked_fields.push("add-bounds");
487+
}
488+
if pip.is_some() {
489+
masked_fields.push("pip");
490+
}
491+
if cache_keys.is_some() {
492+
masked_fields.push("cache_keys");
493+
}
494+
if override_dependencies.is_some() {
495+
masked_fields.push("override-dependencies");
496+
}
497+
if constraint_dependencies.is_some() {
498+
masked_fields.push("constraint-dependencies");
499+
}
500+
if build_constraint_dependencies.is_some() {
501+
masked_fields.push("build-constraint-dependencies");
502+
}
503+
if environments.is_some() {
504+
masked_fields.push("environments");
505+
}
506+
if required_environments.is_some() {
507+
masked_fields.push("required-environments");
508+
}
509+
if !masked_fields.is_empty() {
510+
let field_listing = masked_fields.join("\n- ");
511+
warn_user!(
512+
"Found both a `uv.toml` file and a `[tool.uv]` section in an adjacent `pyproject.toml`. The following fields from `[tool.uv]` will be ignored in favor of the `uv.toml` file:\n- {}",
513+
field_listing,
514+
);
515+
}
516+
}
517+
272518
#[derive(thiserror::Error, Debug)]
273519
pub enum Error {
274520
#[error(transparent)]

0 commit comments

Comments
 (0)