1use anyhow::{Result, anyhow};
2use clap::{Args, ValueEnum};
3
4use uv_warnings::warn_user;
5
6pub trait CompatArgs {
7 fn validate(&self) -> Result<()>;
8}
9
10#[derive(Args)]
16pub struct PipCompileCompatArgs {
17 #[clap(long, hide = true)]
18 allow_unsafe: bool,
19
20 #[clap(long, hide = true)]
21 no_allow_unsafe: bool,
22
23 #[clap(long, hide = true)]
24 reuse_hashes: bool,
25
26 #[clap(long, hide = true)]
27 no_reuse_hashes: bool,
28
29 #[clap(long, hide = true)]
30 resolver: Option<Resolver>,
31
32 #[clap(long, hide = true)]
33 max_rounds: Option<usize>,
34
35 #[clap(long, hide = true)]
36 client_cert: Option<String>,
37
38 #[clap(long, hide = true)]
39 emit_trusted_host: bool,
40
41 #[clap(long, hide = true)]
42 no_emit_trusted_host: bool,
43
44 #[clap(long, hide = true)]
45 config: Option<String>,
46
47 #[clap(long, hide = true)]
48 no_config: bool,
49
50 #[clap(long, hide = true)]
51 emit_options: bool,
52
53 #[clap(long, hide = true)]
54 no_emit_options: bool,
55
56 #[clap(long, hide = true)]
57 pip_args: Option<String>,
58}
59
60impl CompatArgs for PipCompileCompatArgs {
61 fn validate(&self) -> Result<()> {
67 if self.allow_unsafe {
68 warn_user!(
69 "pip-compile's `--allow-unsafe` has no effect (uv can safely pin `pip` and other packages)"
70 );
71 }
72
73 if self.no_allow_unsafe {
74 warn_user!(
75 "pip-compile's `--no-allow-unsafe` has no effect (uv can safely pin `pip` and other packages)"
76 );
77 }
78
79 if self.reuse_hashes {
80 return Err(anyhow!(
81 "pip-compile's `--reuse-hashes` is unsupported (uv doesn't reuse hashes)"
82 ));
83 }
84
85 if self.no_reuse_hashes {
86 warn_user!("pip-compile's `--no-reuse-hashes` has no effect (uv doesn't reuse hashes)");
87 }
88
89 if let Some(resolver) = self.resolver {
90 match resolver {
91 Resolver::Backtracking => {
92 warn_user!(
93 "pip-compile's `--resolver=backtracking` has no effect (uv always backtracks)"
94 );
95 }
96 Resolver::Legacy => {
97 return Err(anyhow!(
98 "pip-compile's `--resolver=legacy` is unsupported (uv always backtracks)"
99 ));
100 }
101 }
102 }
103
104 if self.max_rounds.is_some() {
105 return Err(anyhow!(
106 "pip-compile's `--max-rounds` is unsupported (uv always resolves until convergence)"
107 ));
108 }
109
110 if self.client_cert.is_some() {
111 return Err(anyhow!(
112 "pip-compile's `--client-cert` is unsupported (uv doesn't support dedicated client certificates)"
113 ));
114 }
115
116 if self.emit_trusted_host {
117 return Err(anyhow!(
118 "pip-compile's `--emit-trusted-host` is unsupported"
119 ));
120 }
121
122 if self.no_emit_trusted_host {
123 warn_user!(
124 "pip-compile's `--no-emit-trusted-host` has no effect (uv never emits trusted hosts)"
125 );
126 }
127
128 if self.config.is_some() {
129 return Err(anyhow!(
130 "pip-compile's `--config` is unsupported (uv does not use a configuration file)"
131 ));
132 }
133
134 if self.emit_options {
135 return Err(anyhow!(
136 "pip-compile's `--emit-options` is unsupported (try `--emit-build-options` instead)"
137 ));
138 }
139
140 if self.no_emit_options {
141 warn_user!("pip-compile's `--no-emit-options` has no effect (uv never emits options)");
142 }
143
144 if self.pip_args.is_some() {
145 return Err(anyhow!(
146 "pip-compile's `--pip-args` is unsupported (try passing arguments to uv directly)"
147 ));
148 }
149
150 Ok(())
151 }
152}
153
154#[derive(Args)]
158pub struct PipListCompatArgs {
159 #[clap(long, hide = true)]
160 disable_pip_version_check: bool,
161}
162
163impl CompatArgs for PipListCompatArgs {
164 fn validate(&self) -> Result<()> {
170 if self.disable_pip_version_check {
171 warn_user!("pip's `--disable-pip-version-check` has no effect");
172 }
173
174 Ok(())
175 }
176}
177
178#[derive(Args)]
182pub struct PipSyncCompatArgs {
183 #[clap(short, long, hide = true)]
184 ask: bool,
185
186 #[clap(long, hide = true)]
187 python_executable: Option<String>,
188
189 #[clap(long, hide = true)]
190 user: bool,
191
192 #[clap(long, hide = true)]
193 client_cert: Option<String>,
194
195 #[clap(long, hide = true)]
196 config: Option<String>,
197
198 #[clap(long, hide = true)]
199 no_config: bool,
200
201 #[clap(long, hide = true)]
202 pip_args: Option<String>,
203}
204
205impl CompatArgs for PipSyncCompatArgs {
206 fn validate(&self) -> Result<()> {
212 if self.ask {
213 return Err(anyhow!(
214 "pip-sync's `--ask` is unsupported (uv never asks for confirmation)"
215 ));
216 }
217
218 if self.python_executable.is_some() {
219 return Err(anyhow!(
220 "pip-sync's `--python-executable` is unsupported (to install into a separate Python environment, try setting `VIRTUAL_ENV` instead)"
221 ));
222 }
223
224 if self.user {
225 return Err(anyhow!(
226 "pip-sync's `--user` is unsupported (use a virtual environment instead)"
227 ));
228 }
229
230 if self.client_cert.is_some() {
231 return Err(anyhow!(
232 "pip-sync's `--client-cert` is unsupported (uv doesn't support dedicated client certificates)"
233 ));
234 }
235
236 if self.config.is_some() {
237 return Err(anyhow!(
238 "pip-sync's `--config` is unsupported (uv does not use a configuration file)"
239 ));
240 }
241
242 if self.pip_args.is_some() {
243 return Err(anyhow!(
244 "pip-sync's `--pip-args` is unsupported (try passing arguments to uv directly)"
245 ));
246 }
247
248 Ok(())
249 }
250}
251
252#[derive(Debug, Copy, Clone, ValueEnum)]
253enum Resolver {
254 Backtracking,
255 Legacy,
256}
257
258#[derive(Args)]
262pub struct VenvCompatArgs {
263 #[clap(long, hide = true)]
264 no_seed: bool,
265
266 #[clap(long, hide = true)]
267 no_pip: bool,
268
269 #[clap(long, hide = true)]
270 no_setuptools: bool,
271
272 #[clap(long, hide = true)]
273 no_wheel: bool,
274}
275
276impl CompatArgs for VenvCompatArgs {
277 fn validate(&self) -> Result<()> {
283 if self.no_seed {
284 warn_user!(
285 "virtualenv's `--no-seed` has no effect (uv omits seed packages by default)"
286 );
287 }
288
289 if self.no_pip {
290 warn_user!("virtualenv's `--no-pip` has no effect (uv omits `pip` by default)");
291 }
292
293 if self.no_setuptools {
294 warn_user!(
295 "virtualenv's `--no-setuptools` has no effect (uv omits `setuptools` by default)"
296 );
297 }
298
299 if self.no_wheel {
300 warn_user!("virtualenv's `--no-wheel` has no effect (uv omits `wheel` by default)");
301 }
302
303 Ok(())
304 }
305}
306
307#[derive(Args)]
311pub struct PipUninstallCompatArgs {
312 #[clap(short, long, hide = true)]
316 yes: bool,
317
318 #[clap(long, hide = true)]
319 disable_pip_version_check: bool,
320}
321
322impl CompatArgs for PipUninstallCompatArgs {
323 fn validate(&self) -> Result<()> {
329 if self.yes {
330 warn_user!("`--yes` has no effect (uv never asks for confirmation)");
331 }
332
333 if self.disable_pip_version_check {
334 warn_user!("pip's `--disable-pip-version-check` has no effect");
335 }
336
337 Ok(())
338 }
339}
340
341#[derive(Args)]
345pub struct PipInstallCompatArgs {
346 #[clap(long, hide = true)]
347 disable_pip_version_check: bool,
348
349 #[clap(long, hide = false)]
350 user: bool,
351}
352
353impl CompatArgs for PipInstallCompatArgs {
354 fn validate(&self) -> Result<()> {
360 if self.disable_pip_version_check {
361 warn_user!("pip's `--disable-pip-version-check` has no effect");
362 }
363
364 if self.user {
365 return Err(anyhow!(
366 "pip's `--user` is unsupported (use a virtual environment instead)"
367 ));
368 }
369
370 Ok(())
371 }
372}
373
374#[derive(Args)]
378pub struct PipGlobalCompatArgs {
379 #[clap(long, hide = true)]
380 disable_pip_version_check: bool,
381}
382
383impl CompatArgs for PipGlobalCompatArgs {
384 fn validate(&self) -> Result<()> {
390 if self.disable_pip_version_check {
391 warn_user!("pip's `--disable-pip-version-check` has no effect");
392 }
393
394 Ok(())
395 }
396}