mirror of https://github.com/astral-sh/uv
Allow missing `Scripts` directory (#16206)
With the new Python install manager, the `Scripts` directory reported by Python may not exist. See https://github.com/astral-sh/uv/pull/16205 for a failing CI run: https://github.com/astral-sh/uv/actions/runs/18377230241/job/52354460636?pr=16205#step:4:15 Fixes https://github.com/astral-sh/uv/issues/16204
This commit is contained in:
parent
f0fbda1001
commit
3e6fe1da86
|
|
@ -1289,6 +1289,30 @@ jobs:
|
||||||
./uv run python -c ""
|
./uv run python -c ""
|
||||||
./uv run -p 3.13 python -c ""
|
./uv run -p 3.13 python -c ""
|
||||||
|
|
||||||
|
integration-test-windows-python-install-manager:
|
||||||
|
timeout-minutes: 10
|
||||||
|
needs: build-binary-windows-x86_64
|
||||||
|
name: "integration test | windows python install manager"
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: "Download binary"
|
||||||
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||||
|
with:
|
||||||
|
name: uv-windows-x86_64-${{ github.sha }}
|
||||||
|
|
||||||
|
- name: "Install Python via Python Install manager"
|
||||||
|
run: |
|
||||||
|
# https://www.python.org/downloads/release/pymanager-250/
|
||||||
|
winget install --accept-package-agreements --accept-source-agreements 9NQ7512CXL7T
|
||||||
|
# Call Python Install Manager's py.exe by full path to avoid legacy py.exe
|
||||||
|
& "$env:LOCALAPPDATA\Microsoft\WindowsApps\py.exe" install 3.14
|
||||||
|
|
||||||
|
# https://github.com/astral-sh/uv/issues/16204
|
||||||
|
- name: "Check temporary environment creation"
|
||||||
|
run: |
|
||||||
|
./uv run -p $env:LOCALAPPDATA\Python\pythoncore-3.14-64\python.exe --with numpy python -c "import sys; print(sys.executable)"
|
||||||
|
|
||||||
integration-test-pypy-linux:
|
integration-test-pypy-linux:
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
needs: build-binary-linux-libc
|
needs: build-binary-linux-libc
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use std::borrow::Cow;
|
||||||
use std::env::VarError;
|
use std::env::VarError;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
use std::io;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
|
@ -1099,7 +1100,12 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||||
// Copy each entrypoint from the base environments to the ephemeral environment,
|
// Copy each entrypoint from the base environments to the ephemeral environment,
|
||||||
// updating the Python executable target to ensure they run in the ephemeral
|
// updating the Python executable target to ensure they run in the ephemeral
|
||||||
// environment.
|
// environment.
|
||||||
for entry in fs_err::read_dir(interpreter.scripts())? {
|
let scripts = match fs_err::read_dir(interpreter.scripts()) {
|
||||||
|
Ok(scripts) => scripts,
|
||||||
|
Err(err) if err.kind() == io::ErrorKind::NotFound => continue,
|
||||||
|
Err(err) => return Err(err.into()),
|
||||||
|
};
|
||||||
|
for entry in scripts {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
if !entry.file_type()?.is_file() {
|
if !entry.file_type()?.is_file() {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1200,23 +1206,13 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||||
"Provide a command or script to invoke with `uv run <command>` or `uv run <script>.py`.\n"
|
"Provide a command or script to invoke with `uv run <command>` or `uv run <script>.py`.\n"
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
#[allow(clippy::map_identity)]
|
let scripts = match fs_err::read_dir(interpreter.scripts()) {
|
||||||
let commands = interpreter
|
Ok(scripts) => scripts.into_iter().collect::<Result<Vec<_>, _>>()?,
|
||||||
.scripts()
|
Err(err) if err.kind() == io::ErrorKind::NotFound => Vec::new(),
|
||||||
.read_dir()
|
Err(err) => return Err(err.into()),
|
||||||
.ok()
|
};
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
let commands = scripts
|
||||||
.map(|entry| match entry {
|
|
||||||
Ok(entry) => Ok(entry),
|
|
||||||
Err(err) => {
|
|
||||||
// If we can't read the entry, fail.
|
|
||||||
// This could be a symptom of a more serious problem.
|
|
||||||
warn!("Failed to read entry: {}", err);
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, _>>()?
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|entry| {
|
.filter(|entry| {
|
||||||
entry
|
entry
|
||||||
|
|
@ -1226,7 +1222,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||||
.map(|entry| entry.path())
|
.map(|entry| entry.path())
|
||||||
.filter(|path| is_executable(path))
|
.filter(|path| is_executable(path))
|
||||||
.map(|path| {
|
.map(|path| {
|
||||||
if cfg!(windows)
|
let path = if cfg!(windows)
|
||||||
&& path
|
&& path
|
||||||
.extension()
|
.extension()
|
||||||
.is_some_and(|exe| exe == std::env::consts::EXE_EXTENSION)
|
.is_some_and(|exe| exe == std::env::consts::EXE_EXTENSION)
|
||||||
|
|
@ -1235,9 +1231,8 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||||
path.with_extension("")
|
path.with_extension("")
|
||||||
} else {
|
} else {
|
||||||
path
|
path
|
||||||
}
|
};
|
||||||
})
|
|
||||||
.map(|path| {
|
|
||||||
path.file_name()
|
path.file_name()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue