Skip to content

Commit fef1378

Browse files
committed
tweak approach
1 parent 429ab6b commit fef1378

File tree

1 file changed

+44
-26
lines changed

1 file changed

+44
-26
lines changed

R/package.R

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -310,41 +310,47 @@ initialize_python <- function(required_module = NULL, use_environment = NULL) {
310310
#' Returns `FALSE` if required packages are missing, but also issues warnings
311311
#' containing more details about the missing packages.
312312
check_virtualenv_required_packages <- function(config) {
313-
packages <- py_reqs_get()$packages
314-
315-
if (length(packages) == 0) {
316-
return(invisible(TRUE))
313+
314+
# TODO: also check py_require()$python_version.
315+
# TODO: also warn if py_require() is called after reticulate has initialize Python.
316+
317+
# we don't install uv if it's not yet installed
318+
uv <- uv_binary(bootstrap_install = FALSE)
319+
if (is.null(uv)) {
320+
return(invisible(NULL))
317321
}
318-
319-
args <- c("pip", "install", packages, "--dry-run", "--no-deps")
320-
321322
# force uv to use the selected python binary.
322323
# in principle this could be ommited assuming that VIRTUAL_ENV is set
323-
print(config$python)
324-
args <- c(args, "--python", config$python)
325-
326-
# we don't install uv if it's not yet installed
327-
cmd <- uv_binary(bootstrap_install = FALSE)
328-
if (is.null(cmd)) {
329-
return(invisible(NULL))
324+
325+
packages <- py_require()$packages
326+
if (length(packages) == 0) {
327+
return(invisible(TRUE))
330328
}
331329

330+
args <- c("pip install --dry-run --no-deps",
331+
"--color never --no-progress",
332+
"--no-build",
333+
# "--verbose",
334+
"--offline", "--no-config",
335+
"--python", maybe_shQuote(config$python),
336+
maybe_shQuote(packages))
337+
332338
suppressWarnings({
333-
out <- system2(cmd, args, stdout = TRUE, stderr = TRUE)
339+
pip_output <- uv_exec(args, stdout = TRUE, stderr = TRUE)
334340
})
335341

336-
status <- attr(out, "status") %||% 0L
342+
status <- attr(pip_output, "status") %||% 0L
337343
if (status != 0L) {
338344
# check failed.
339345
# there are a few possible reasons:
340-
# 1) a requiremed package is not availble in the index.
346+
# 1) a required package is not available in the index.
341347
# No solution found when resolving dependencies:
342-
# ╰─▶ Because <pkg> was not found in the package registry and you require <pkg>,
348+
# ╰─▶ Because <pkg> was not found in the package registry and you require <pkg>,
343349
# we can conclude that your requirements are unsatisfiable.
344-
# 2) Any faillure to access the index (timeouts, network issues, etc)
350+
# 2) Any failure to access the index (timeouts, network issues, etc)
345351
# same error as above. Since there's no way to differentiate these cases,
346352
# we just return NULL.
347-
return(invisible(NULL))
353+
return(invisible(NULL))
348354
}
349355

350356
# uv pip doesn't have an option to produce structured output,
@@ -353,15 +359,27 @@ check_virtualenv_required_packages <- function(config) {
353359
# > Would install <n> packages
354360
# we use that to determine if any packages would be installed
355361
pattern <- "Would install (\\d+) package(s)?"
356-
would_install <- any(grepl(pattern, out))
362+
would_install <- any(grepl(pattern, pip_output))
357363

358364
if (would_install) {
359-
out <- sub("Would install", "Missing", out)
360-
out <- sub("Would install", "Missing", out)
365+
# subset the py_require()$packages vector to keep only those that
366+
# match output from `uv pip install`.
367+
368+
# keep lines that list package versions like " + docutils==1.2.3"
369+
would_install_pkgs <- grep("==", pip_output, fixed = TRUE, value = TRUE)
370+
371+
# extract just the package name like "docutils"
372+
would_install_pkgs <- sub("(...)([^=]+)(==.*)", "\\2", would_install_pkgs)
373+
374+
# subset packages to keep only entries found in `uv pip` output.
375+
would_install_pkgs <- packages[
376+
vapply(packages, function(pkg) any(startsWith(pkg, would_install_pkgs)), TRUE,
377+
USE.NAMES = FALSE)
378+
]
361379
warning(
362-
"Some packages were required with `py_require()` but are not installed in the",
363-
"resolved virtual environment.\n",
364-
paste0(out, collapse="\n"),
380+
"Some Python package requirements declared via `py_require()` are not",
381+
" installed in the selected Python environment: (", config$python, ")\n",
382+
" ", paste0(would_install_pkgs, collapse=" "),
365383
call. = FALSE
366384
)
367385
return(invisible(FALSE))

0 commit comments

Comments
 (0)