Skip to content

Commit abc68fc

Browse files
authored
Consider pythonw when copying entrypoints in uv run (#15134)
## Summary Follow up from #15068 (comment) It seems when copying entrypoints we're ignoring whether it was pythonw vs not. ## Test Plan Updated existing test.
1 parent 7f1eaf4 commit abc68fc

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

crates/uv/src/commands/project/run.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1937,7 +1937,15 @@ fn copy_entrypoint(
19371937
return Ok(());
19381938
};
19391939

1940-
let launcher = launcher.with_python_path(python_executable.to_path_buf());
1940+
let is_gui = launcher.python_path.ends_with("pythonw.exe");
1941+
1942+
let python_path = if is_gui {
1943+
python_executable.with_file_name("pythonw.exe")
1944+
} else {
1945+
python_executable.to_path_buf()
1946+
};
1947+
1948+
let launcher = launcher.with_python_path(python_path);
19411949
let mut file = fs_err::OpenOptions::new()
19421950
.create_new(true)
19431951
.write(true)

crates/uv/tests/it/run.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,9 @@ fn run_with_overlay_interpreter() -> Result<()> {
13441344
13451345
[project.scripts]
13461346
main = "foo:main"
1347+
1348+
[project.gui-scripts]
1349+
main_gui = "foo:main_gui"
13471350
"#
13481351
})?;
13491352

@@ -1362,10 +1365,19 @@ fn run_with_overlay_interpreter() -> Result<()> {
13621365
base = Path(sys.executable)
13631366
shutil.copyfile(base.with_name("main").with_suffix(base.suffix), sys.argv[1])
13641367
1368+
def copy_gui_entrypoint():
1369+
base = Path(sys.executable)
1370+
shutil.copyfile(base.with_name("main_gui").with_suffix(base.suffix), sys.argv[1])
1371+
13651372
def main():
13661373
show_python()
13671374
if len(sys.argv) > 1:
13681375
copy_entrypoint()
1376+
1377+
def main_gui():
1378+
show_python()
1379+
if len(sys.argv) > 1:
1380+
copy_gui_entrypoint()
13691381
"#
13701382
})?;
13711383

@@ -1390,6 +1402,20 @@ fn run_with_overlay_interpreter() -> Result<()> {
13901402
+ iniconfig==2.0.0
13911403
");
13921404

1405+
// The project's gui entrypoint should be rewritten to use the overlay interpreter.
1406+
#[cfg(windows)]
1407+
uv_snapshot!(context.filters(), context.run().arg("--with").arg("iniconfig").arg("main_gui").arg(context.temp_dir.child("main_gui").as_os_str()), @r"
1408+
success: true
1409+
exit_code: 0
1410+
----- stdout -----
1411+
[CACHE_DIR]/builds-v0/[TMP]/pythonw
1412+
1413+
----- stderr -----
1414+
Resolved 6 packages in [TIME]
1415+
Audited 4 packages in [TIME]
1416+
Resolved 1 package in [TIME]
1417+
");
1418+
13931419
#[cfg(unix)]
13941420
insta::with_settings!({
13951421
filters => context.filters(),
@@ -1439,9 +1465,26 @@ fn run_with_overlay_interpreter() -> Result<()> {
14391465
+ sniffio==1.3.1
14401466
");
14411467

1468+
// When layering the project on top (via `--with`), the overlay gui interpreter also should be used.
1469+
#[cfg(windows)]
1470+
uv_snapshot!(context.filters(), context.run().arg("--no-project").arg("--gui-script").arg("--with").arg(".").arg("main_gui"), @r"
1471+
success: true
1472+
exit_code: 0
1473+
----- stdout -----
1474+
[CACHE_DIR]/builds-v0/[TMP]/pythonw
1475+
1476+
----- stderr -----
1477+
Resolved 4 packages in [TIME]
1478+
");
1479+
14421480
// Switch to a relocatable virtual environment.
14431481
context.venv().arg("--relocatable").assert().success();
14441482

1483+
// Cleanup previous shutil
1484+
fs_err::remove_file(context.temp_dir.child("main"))?;
1485+
#[cfg(windows)]
1486+
fs_err::remove_file(context.temp_dir.child("main_gui"))?;
1487+
14451488
// The project's entrypoint should be rewritten to use the overlay interpreter.
14461489
uv_snapshot!(context.filters(), context.run().arg("--with").arg("iniconfig").arg("main").arg(context.temp_dir.child("main").as_os_str()), @r"
14471490
success: true
@@ -1455,6 +1498,20 @@ fn run_with_overlay_interpreter() -> Result<()> {
14551498
Resolved 1 package in [TIME]
14561499
");
14571500

1501+
// The project's gui entrypoint should be rewritten to use the overlay interpreter.
1502+
#[cfg(windows)]
1503+
uv_snapshot!(context.filters(), context.run().arg("--with").arg("iniconfig").arg("main_gui").arg(context.temp_dir.child("main_gui").as_os_str()), @r"
1504+
success: true
1505+
exit_code: 0
1506+
----- stdout -----
1507+
[CACHE_DIR]/builds-v0/[TMP]/pythonw
1508+
1509+
----- stderr -----
1510+
Resolved 6 packages in [TIME]
1511+
Audited 4 packages in [TIME]
1512+
Resolved 1 package in [TIME]
1513+
");
1514+
14581515
// The package, its dependencies, and the overlay dependencies should be available.
14591516
context
14601517
.run()
@@ -1498,6 +1555,18 @@ fn run_with_overlay_interpreter() -> Result<()> {
14981555
Resolved 4 packages in [TIME]
14991556
");
15001557

1558+
// When layering the project on top (via `--with`), the overlay gui interpreter also should be used.
1559+
#[cfg(windows)]
1560+
uv_snapshot!(context.filters(), context.run().arg("--no-project").arg("--gui-script").arg("--with").arg(".").arg("main_gui"), @r"
1561+
success: true
1562+
exit_code: 0
1563+
----- stdout -----
1564+
[CACHE_DIR]/builds-v0/[TMP]/pythonw
1565+
1566+
----- stderr -----
1567+
Resolved 4 packages in [TIME]
1568+
");
1569+
15011570
Ok(())
15021571
}
15031572

0 commit comments

Comments
 (0)