1
1
use std:: process:: Command ;
2
2
3
3
use anyhow:: Result ;
4
+ use assert_cmd:: assert:: OutputAssertExt ;
4
5
use assert_fs:: {
5
6
assert:: PathAssert ,
6
7
fixture:: { FileTouch , FileWriteStr , PathChild } ,
@@ -178,15 +179,20 @@ fn tool_install() {
178
179
}
179
180
180
181
#[ test]
181
- fn tool_install_with_global_python ( ) -> Result < ( ) > {
182
- let context = TestContext :: new_with_versions ( & [ "3.11" , "3.12" ] )
182
+ fn tool_install_python_from_global_version_file ( ) {
183
+ let context = TestContext :: new_with_versions ( & [ "3.11" , "3.12" , "3.13" ] )
183
184
. with_filtered_counts ( )
184
185
. with_filtered_exe_suffix ( ) ;
185
186
let tool_dir = context. temp_dir . child ( "tools" ) ;
186
187
let bin_dir = context. temp_dir . child ( "bin" ) ;
187
- let uv = context. user_config_dir . child ( "uv" ) ;
188
- let versions = uv. child ( ".python-version" ) ;
189
- versions. write_str ( "3.11" ) ?;
188
+
189
+ // Pin to 3.12
190
+ context
191
+ . python_pin ( )
192
+ . arg ( "3.12" )
193
+ . arg ( "--global" )
194
+ . assert ( )
195
+ . success ( ) ;
190
196
191
197
// Install a tool
192
198
uv_snapshot ! ( context. filters( ) , context. tool_install( )
@@ -212,37 +218,158 @@ fn tool_install_with_global_python() -> Result<()> {
212
218
Installed 1 executable: flask
213
219
"### ) ;
214
220
215
- tool_dir. child ( "flask" ) . assert ( predicate:: path:: is_dir ( ) ) ;
216
- assert ! (
217
- bin_dir
218
- . child( format!( "flask{}" , std:: env:: consts:: EXE_SUFFIX ) )
219
- . exists( )
220
- ) ;
221
-
222
- uv_snapshot ! ( context. filters( ) , Command :: new( "flask" ) . arg( "--version" ) . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r###"
221
+ // It should use the version from the global file
222
+ uv_snapshot ! ( context. filters( ) , Command :: new( "flask" ) . arg( "--version" ) . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r"
223
223
success: true
224
224
exit_code: 0
225
225
----- stdout -----
226
- Python 3.11 .[X]
226
+ Python 3.12 .[X]
227
227
Flask 3.0.2
228
228
Werkzeug 3.0.1
229
229
230
230
----- stderr -----
231
- "### ) ;
231
+ " ) ;
232
232
233
233
// Change global version
234
- uv_snapshot ! ( context. filters( ) , context. python_pin( ) . arg( "3.12" ) . arg( "--global" ) ,
235
- @r"
234
+ context
235
+ . python_pin ( )
236
+ . arg ( "3.13" )
237
+ . arg ( "--global" )
238
+ . assert ( )
239
+ . success ( ) ;
240
+
241
+ // Installing flask again should be a no-op, even though the global pin changed
242
+ uv_snapshot ! ( context. filters( ) , context. tool_install( )
243
+ . arg( "flask" )
244
+ . env( EnvVars :: UV_TOOL_DIR , tool_dir. as_os_str( ) )
245
+ . env( EnvVars :: XDG_BIN_HOME , bin_dir. as_os_str( ) )
246
+ . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r"
236
247
success: true
237
248
exit_code: 0
238
249
----- stdout -----
239
- Updated `[UV_USER_CONFIG_DIR]/.python-version` from `3.11` -> `3.12`
240
250
241
251
----- stderr -----
242
- "
243
- ) ;
252
+ `flask` is already installed
253
+ " ) ;
244
254
245
- // Install flask again
255
+ uv_snapshot ! ( context. filters( ) , Command :: new( "flask" ) . arg( "--version" ) . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r"
256
+ success: true
257
+ exit_code: 0
258
+ ----- stdout -----
259
+ Python 3.12.[X]
260
+ Flask 3.0.2
261
+ Werkzeug 3.0.1
262
+
263
+ ----- stderr -----
264
+ " ) ;
265
+
266
+ // Using `--upgrade` forces us to check the environment
267
+ uv_snapshot ! ( context. filters( ) , context. tool_install( )
268
+ . arg( "flask" )
269
+ . arg( "--upgrade" )
270
+ . env( EnvVars :: UV_TOOL_DIR , tool_dir. as_os_str( ) )
271
+ . env( EnvVars :: XDG_BIN_HOME , bin_dir. as_os_str( ) )
272
+ . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r"
273
+ success: true
274
+ exit_code: 0
275
+ ----- stdout -----
276
+
277
+ ----- stderr -----
278
+ Resolved [N] packages in [TIME]
279
+ Audited [N] packages in [TIME]
280
+ Installed 1 executable: flask
281
+ " ) ;
282
+
283
+ // This will not change to the new global pin, since there was not a reinstall request
284
+ uv_snapshot ! ( context. filters( ) , Command :: new( "flask" ) . arg( "--version" ) . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r"
285
+ success: true
286
+ exit_code: 0
287
+ ----- stdout -----
288
+ Python 3.12.[X]
289
+ Flask 3.0.2
290
+ Werkzeug 3.0.1
291
+
292
+ ----- stderr -----
293
+ " ) ;
294
+
295
+ // Using `--reinstall` forces us to install flask again
296
+ uv_snapshot ! ( context. filters( ) , context. tool_install( )
297
+ . arg( "flask" )
298
+ . arg( "--reinstall" )
299
+ . env( EnvVars :: UV_TOOL_DIR , tool_dir. as_os_str( ) )
300
+ . env( EnvVars :: XDG_BIN_HOME , bin_dir. as_os_str( ) )
301
+ . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r"
302
+ success: true
303
+ exit_code: 0
304
+ ----- stdout -----
305
+
306
+ ----- stderr -----
307
+ Ignoring existing environment for `flask`: the Python interpreter does not match the environment interpreter
308
+ Resolved [N] packages in [TIME]
309
+ Prepared [N] packages in [TIME]
310
+ Installed [N] packages in [TIME]
311
+ + blinker==1.7.0
312
+ + click==8.1.7
313
+ + flask==3.0.2
314
+ + itsdangerous==2.1.2
315
+ + jinja2==3.1.3
316
+ + markupsafe==2.1.5
317
+ + werkzeug==3.0.1
318
+ Installed 1 executable: flask
319
+ " ) ;
320
+
321
+ // This will change to the new global pin, since there was not an explicit request recorded in
322
+ // the receipt
323
+ uv_snapshot ! ( context. filters( ) , Command :: new( "flask" ) . arg( "--version" ) . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r"
324
+ success: true
325
+ exit_code: 0
326
+ ----- stdout -----
327
+ Python 3.13.[X]
328
+ Flask 3.0.2
329
+ Werkzeug 3.0.1
330
+
331
+ ----- stderr -----
332
+ " ) ;
333
+
334
+ // If we request a specific Python version, it takes precedence over the pin
335
+ uv_snapshot ! ( context. filters( ) , context. tool_install( )
336
+ . arg( "flask" )
337
+ . arg( "--python" )
338
+ . arg( "3.11" )
339
+ . env( EnvVars :: UV_TOOL_DIR , tool_dir. as_os_str( ) )
340
+ . env( EnvVars :: XDG_BIN_HOME , bin_dir. as_os_str( ) )
341
+ . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r"
342
+ success: true
343
+ exit_code: 0
344
+ ----- stdout -----
345
+
346
+ ----- stderr -----
347
+ Ignoring existing environment for `flask`: the requested Python interpreter does not match the environment interpreter
348
+ Resolved [N] packages in [TIME]
349
+ Prepared [N] packages in [TIME]
350
+ Installed [N] packages in [TIME]
351
+ + blinker==1.7.0
352
+ + click==8.1.7
353
+ + flask==3.0.2
354
+ + itsdangerous==2.1.2
355
+ + jinja2==3.1.3
356
+ + markupsafe==2.1.5
357
+ + werkzeug==3.0.1
358
+ Installed 1 executable: flask
359
+ " ) ;
360
+
361
+ uv_snapshot ! ( context. filters( ) , Command :: new( "flask" ) . arg( "--version" ) . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r"
362
+ success: true
363
+ exit_code: 0
364
+ ----- stdout -----
365
+ Python 3.11.[X]
366
+ Flask 3.0.2
367
+ Werkzeug 3.0.1
368
+
369
+ ----- stderr -----
370
+ " ) ;
371
+
372
+ // Use `--reinstall` to install flask again
246
373
uv_snapshot ! ( context. filters( ) , context. tool_install( )
247
374
. arg( "flask" )
248
375
. arg( "--reinstall" )
@@ -268,9 +395,8 @@ fn tool_install_with_global_python() -> Result<()> {
268
395
Installed 1 executable: flask
269
396
" ) ;
270
397
271
- // Currently, when reinstalling a tool we use the original version the tool
272
- // was installed with, not the most up-to-date global version
273
- uv_snapshot ! ( context. filters( ) , Command :: new( "flask" ) . arg( "--version" ) . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r###"
398
+ // We should continue to use the version from the install, not the global pin
399
+ uv_snapshot ! ( context. filters( ) , Command :: new( "flask" ) . arg( "--version" ) . env( EnvVars :: PATH , bin_dir. as_os_str( ) ) , @r"
274
400
success: true
275
401
exit_code: 0
276
402
----- stdout -----
@@ -279,9 +405,7 @@ fn tool_install_with_global_python() -> Result<()> {
279
405
Werkzeug 3.0.1
280
406
281
407
----- stderr -----
282
- "### ) ;
283
-
284
- Ok ( ( ) )
408
+ " ) ;
285
409
}
286
410
287
411
#[ test]
0 commit comments