@@ -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.
312312check_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