From d01169c7f419bf848d7e603f410a8d5b2e577120 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 23 Mar 2023 10:44:19 +0200 Subject: [PATCH 1/3] Add verbosity to download output and errors --- R/install.R | 62 +++++++++++++++++++---------------- tests/testthat/test-install.R | 46 ++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 28 deletions(-) diff --git a/R/install.R b/R/install.R index 7820881c3..ff1e565a3 100644 --- a/R/install.R +++ b/R/install.R @@ -141,7 +141,7 @@ install_cmdstan <- function(dir = NULL, dir_cmdstan <- file.path(dir, cmdstan_ver) dest_file <- file.path(dir, tar_gz_file) } else { - ver <- latest_released_version() + ver <- latest_released_version(quiet = quiet) message("* Latest CmdStan release is v", ver) cmdstan_ver <- paste0("cmdstan-", ver, cmdstan_arch_suffix(ver)) tar_gz_file <- paste0(cmdstan_ver, ".tar.gz") @@ -154,7 +154,7 @@ install_cmdstan <- function(dir = NULL, if (!check_install_dir(dir_cmdstan, overwrite)) { return(invisible(NULL)) } - tar_downloaded <- download_with_retries(download_url, dest_file) + tar_downloaded <- download_with_retries(download_url, dest_file, quiet = quiet) if (!tar_downloaded) { if (!is.null(version)) { stop("Download of CmdStan failed. Please check if the supplied version number is valid.", call. = FALSE) @@ -360,45 +360,51 @@ github_download_url <- function(version_number) { } # get version number of latest release -latest_released_version <- function() { +latest_released_version <- function(quiet=TRUE) { dest_file <- tempfile(pattern = "releases-", fileext = ".json") download_url <- "https://api.github.com/repos/stan-dev/cmdstan/releases/latest" - release_list_downloaded <- download_with_retries(download_url, dest_file) - if (!release_list_downloaded) { - stop("GitHub download of release list failed.", call. = FALSE) - } + release_list_downloaded <- download_with_retries(download_url, dest_file, quiet = quiet) release <- jsonlite::read_json(dest_file) sub("v", "", release$tag_name) } +try_download <- function(download_url, destination_file, + quiet = TRUE, + stop_on_error = TRUE) { + download_status <- try( + suppressWarnings( + utils::download.file(url = download_url, + destfile = destination_file, + quiet = quiet, + headers = github_auth_token()) + ), + silent = TRUE + ) + if (inherits(download_status, "try-error") && isTRUE(stop_on_error)) { + stop("Download failed with error message: ", + attr(download_status, "condition")$message, + call. = FALSE) + } + download_status +} + # download with retries and pauses download_with_retries <- function(download_url, destination_file, retries = 5, pause_sec = 5, quiet = TRUE) { - - download_rc <- 1 - while (retries > 0 && download_rc != 0) { - try( - suppressWarnings( - download_rc <- utils::download.file(url = download_url, - destfile = destination_file, - quiet = quiet, - headers = github_auth_token()) - ), - silent = TRUE - ) - if (download_rc != 0) { - Sys.sleep(pause_sec) - } - retries <- retries - 1 - } - if (download_rc == 0) { - TRUE - } else { - FALSE + download_rc <- try_download(download_url, destination_file, + quiet = quiet, stop_on_error = FALSE) + num_retries <- 1 + while (num_retries < retries && inherits(download_rc, "try-error")) { + Sys.sleep(pause_sec) + num_retries <- num_retries + 1 + download_rc <- try_download(download_url, destination_file, + quiet = quiet, + stop_on_error = (num_retries == (retries))) } + TRUE } build_cmdstan <- function(dir, diff --git a/tests/testthat/test-install.R b/tests/testthat/test-install.R index 2d312e8a6..f79efed69 100644 --- a/tests/testthat/test-install.R +++ b/tests/testthat/test-install.R @@ -198,3 +198,49 @@ test_that("github_download_url constructs correct url", { ) }) +test_that("Downloads respect quiet argument", { + if (getRversion() < '3.5.0') { + dir <- tempdir() + } else { + dir <- tempdir(check = TRUE) + } + version <- latest_released_version() + + ver_msg <- "trying URL 'https://api.github.com/repos/stan-dev/cmdstan/releases/latest'" + download_msg <- paste0("trying URL 'https://github.com/stan-dev/cmdstan/releases/download/v", + version, "/cmdstan-", version, ".tar.gz'") + + # expect_message has trouble capturing the messages from download.file + # so handle manually + install_normal <- suppressWarnings( + capture.output(install_cmdstan(dir = dir, overwrite = TRUE, quiet = FALSE), + type = "message") + ) + install_quiet <- suppressWarnings( + capture.output(install_cmdstan(dir = dir, overwrite = TRUE, quiet = TRUE), + type = "message") + ) + + expect_true(any(grepl(ver_msg, install_normal, fixed = TRUE))) + expect_true(any(grepl(download_msg, install_normal, fixed = TRUE))) + + expect_false(any(grepl(ver_msg, install_quiet, fixed = TRUE))) + expect_false(any(grepl(download_msg, install_quiet, fixed = TRUE))) +}) + +test_that("Download failures return error message", { + if (getRversion() < '3.5.0') { + dir <- tempdir() + } else { + dir <- tempdir(check = TRUE) + } + + expect_error({ + # Use an invalid proxy address to force a download failure + withr::with_envvar( + c("http_proxy"="invalid","https_proxy"="invalid"), + install_cmdstan(dir = dir, overwrite = TRUE) + )}, + "Download failed with error message: cannot open URL 'https://api.github.com/repos/stan-dev/cmdstan/releases/latest'") +}) + From a6deba59a409891d21b9c26e4a71045f904f0bad Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 23 Mar 2023 10:51:56 +0200 Subject: [PATCH 2/3] Fix retries typo --- R/install.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/install.R b/R/install.R index ff1e565a3..2905b7c16 100644 --- a/R/install.R +++ b/R/install.R @@ -396,7 +396,7 @@ download_with_retries <- function(download_url, quiet = TRUE) { download_rc <- try_download(download_url, destination_file, quiet = quiet, stop_on_error = FALSE) - num_retries <- 1 + num_retries <- 0 while (num_retries < retries && inherits(download_rc, "try-error")) { Sys.sleep(pause_sec) num_retries <- num_retries + 1 From 2a6d2c9f5445339ba07d70db437cb51b6f2b4bcf Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 23 Mar 2023 13:04:30 +0200 Subject: [PATCH 3/3] Align error returns with existing --- R/install.R | 34 ++++++++++++++++------------------ tests/testthat/test-install.R | 6 +++--- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/R/install.R b/R/install.R index 2905b7c16..b968ce2a4 100644 --- a/R/install.R +++ b/R/install.R @@ -155,14 +155,15 @@ install_cmdstan <- function(dir = NULL, return(invisible(NULL)) } tar_downloaded <- download_with_retries(download_url, dest_file, quiet = quiet) - if (!tar_downloaded) { + if (inherits(tar_downloaded, "try-error")) { + error_msg <- paste("Download of CmdStan failed with error:", + attr(tar_downloaded, "condition")$message) if (!is.null(version)) { - stop("Download of CmdStan failed. Please check if the supplied version number is valid.", call. = FALSE) + error_msg <- paste0(error_msg, "\nPlease check if the supplied version number is valid.") + } else if (!is.null(release_url)) { + error_msg <- paste0(error_msg, "\nPlease check if the supplied release URL is valid.") } - if (!is.null(release_url)) { - stop("Download of CmdStan failed. Please check if the supplied release URL is valid.", call. = FALSE) - } - stop("Download of CmdStan failed. Please try again.", call. = FALSE) + stop(error_msg, call. = FALSE) } message("* Download complete") message("* Unpacking archive...") @@ -364,13 +365,17 @@ latest_released_version <- function(quiet=TRUE) { dest_file <- tempfile(pattern = "releases-", fileext = ".json") download_url <- "https://api.github.com/repos/stan-dev/cmdstan/releases/latest" release_list_downloaded <- download_with_retries(download_url, dest_file, quiet = quiet) + if (inherits(release_list_downloaded, "try-error")) { + stop("GitHub download of release list failed with error: ", + attr(release_list_downloaded, "condition")$message, + call. = FALSE) + } release <- jsonlite::read_json(dest_file) sub("v", "", release$tag_name) } try_download <- function(download_url, destination_file, - quiet = TRUE, - stop_on_error = TRUE) { + quiet = TRUE) { download_status <- try( suppressWarnings( utils::download.file(url = download_url, @@ -380,11 +385,6 @@ try_download <- function(download_url, destination_file, ), silent = TRUE ) - if (inherits(download_status, "try-error") && isTRUE(stop_on_error)) { - stop("Download failed with error message: ", - attr(download_status, "condition")$message, - call. = FALSE) - } download_status } @@ -395,16 +395,14 @@ download_with_retries <- function(download_url, pause_sec = 5, quiet = TRUE) { download_rc <- try_download(download_url, destination_file, - quiet = quiet, stop_on_error = FALSE) + quiet = quiet) num_retries <- 0 while (num_retries < retries && inherits(download_rc, "try-error")) { Sys.sleep(pause_sec) num_retries <- num_retries + 1 - download_rc <- try_download(download_url, destination_file, - quiet = quiet, - stop_on_error = (num_retries == (retries))) + download_rc <- try_download(download_url, destination_file, quiet = quiet) } - TRUE + download_rc } build_cmdstan <- function(dir, diff --git a/tests/testthat/test-install.R b/tests/testthat/test-install.R index f79efed69..02c2ebacd 100644 --- a/tests/testthat/test-install.R +++ b/tests/testthat/test-install.R @@ -75,12 +75,12 @@ test_that("install_cmdstan() errors if it times out", { test_that("install_cmdstan() errors if invalid version or URL", { expect_error( install_cmdstan(version = "2.23.2", wsl = os_is_wsl()), - "Download of CmdStan failed. Please check if the supplied version number is valid." + "Download of CmdStan failed with error: cannot open URL 'https://github.com/stan-dev/cmdstan/releases/download/v2.23.2/cmdstan-2.23.2.tar.gz'\nPlease check if the supplied version number is valid." ) expect_error( install_cmdstan(release_url = "https://github.com/stan-dev/cmdstan/releases/download/v2.23.2/cmdstan-2.23.2.tar.gz", wsl = os_is_wsl()), - "Download of CmdStan failed. Please check if the supplied release URL is valid." + "Download of CmdStan failed with error: cannot open URL 'https://github.com/stan-dev/cmdstan/releases/download/v2.23.2/cmdstan-2.23.2.tar.gz'\nPlease check if the supplied release URL is valid." ) expect_error( install_cmdstan(release_url = "https://github.com/stan-dev/cmdstan/releases/tag/v2.24.0", wsl = os_is_wsl()), @@ -241,6 +241,6 @@ test_that("Download failures return error message", { c("http_proxy"="invalid","https_proxy"="invalid"), install_cmdstan(dir = dir, overwrite = TRUE) )}, - "Download failed with error message: cannot open URL 'https://api.github.com/repos/stan-dev/cmdstan/releases/latest'") + "GitHub download of release list failed with error: cannot open URL 'https://api.github.com/repos/stan-dev/cmdstan/releases/latest'") })