Skip to content

Commit 190bee8

Browse files
authored
Merge pull request #6 from eea/develop
few improvements
2 parents 4d9949b + 4b05f45 commit 190bee8

File tree

6 files changed

+134
-47
lines changed

6 files changed

+134
-47
lines changed

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ Imports:
2323
magrittr,
2424
htmltools,
2525
stringr,
26-
humanize
26+
scales,
27+
progress
2728
Depends:
2829
R (>= 2.10),
2930
Suggests:

R/client.R

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ Client <- R6::R6Class("Client",
8585
error = function(err) {
8686
resp <- httr2::last_response()
8787

88-
if (resp$status_code == 403 || resp$status_code == 401) {
88+
if (!is.null(resp) && (resp$status_code == 403 || resp$status_code == 401)) {
8989
private$auth$get_token()
9090
req <- req %>% httr2::req_headers(Authorization = paste("Bearer", private$auth$token()))
9191

@@ -94,13 +94,11 @@ Client <- R6::R6Class("Client",
9494
req %>% httr2::req_perform()
9595
},
9696
error = function(err) {
97-
error_message <- private$extract_error_message(resp)
98-
stop(paste("Network Error:", error_message, sep = "\n"))
97+
stop(format_error_message(err))
9998
}
10099
)
101100
} else {
102-
error_message <- private$extract_error_message(resp)
103-
stop(paste("Network Error:", error_message, sep = "\n"))
101+
stop(format_error_message(resp))
104102
}
105103
}
106104
)
@@ -263,7 +261,7 @@ Client <- R6::R6Class("Client",
263261
url <- paste0(self$apiUrl, "/datasets")
264262
req <- httr2::request(url) %>%
265263
httr2::req_method("GET") %>%
266-
httr2::req_url_query(q = pattern, startIndex = 0, itemsPerPage = 10)
264+
httr2::req_url_query(q = pattern, startIndex = 0, itemsPerPage = 100)
267265

268266
tryCatch(
269267
{
@@ -272,6 +270,7 @@ Client <- R6::R6Class("Client",
272270
lapply(datasets, private$extract_dataset_meta)
273271
},
274272
error = function(err) {
273+
print(err)
275274
stop(paste("Datasets query failed"))
276275
}
277276
)
@@ -287,7 +286,7 @@ Client <- R6::R6Class("Client",
287286
#' @seealso \code{\link[=SearchResults]{SearchResults}} for details on the returned object.
288287
#' @importFrom httr2 request req_method req_body_json
289288
#' @importFrom stringr str_detect
290-
#' @importFrom humanize natural_size
289+
#' @importFrom scales label_bytes
291290
#' @export
292291
search = function(json_query, limit = NULL) {
293292
json_query <- strip_off_template_placeholders(json_query)
@@ -306,13 +305,17 @@ Client <- R6::R6Class("Client",
306305
search_results <- SearchResults$new(self, results, query$dataset_id)
307306

308307
message(paste("Found", search_results$total_count, "files"))
309-
message(paste("Total Size", humanize::natural_size(search_results$total_size)))
308+
message(paste("Total Size", scales::label_bytes()(search_results$total_size)))
310309

311310
search_results
312311
},
313312
error = function(err) {
314-
warning("Search query failed")
315-
stop(err)
313+
msg <- sprintf(
314+
"Failed to search data:\n%s\n\nOriginal error:\n%s",
315+
conditionMessage(err),
316+
capture.output(str(err))
317+
)
318+
stop(msg)
316319
}
317320
)
318321
},
@@ -342,7 +345,6 @@ Client <- R6::R6Class("Client",
342345

343346
if (to_json) {
344347
resp <- jsonlite::toJSON(resp, pretty = TRUE, auto_unbox = TRUE, digits = 17)
345-
print(resp)
346348
}
347349
resp
348350
},
@@ -501,18 +503,6 @@ Client <- R6::R6Class("Client",
501503
"doi" = doi,
502504
"thumbnails" = meta[["thumbnails"]]
503505
)
504-
},
505-
extract_error_message = function(resp) {
506-
content_type <- httr2::resp_content_type(resp)
507-
508-
if (grepl("application/json", content_type)) {
509-
resp %>%
510-
httr2::resp_body_json() %>%
511-
jsonlite::toJSON(pretty = TRUE, auto_unbox = TRUE, digits = 17)
512-
} else {
513-
# For other content types (e.g., text)
514-
resp %>% httr2::resp_body_string()
515-
}
516506
}
517507
)
518508
)

R/paginator.R

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,12 @@ Paginator <- R6::R6Class("Paginator",
3636
results
3737
},
3838
error = function(err) {
39-
error = paste("Error when getting data with paginator", err, sep = "\n")
40-
stop(error)
39+
msg <- sprintf(
40+
"Failed to retrieve data using paginator:\n%s\n\nOriginal error:\n%s",
41+
conditionMessage(err),
42+
capture.output(str(err))
43+
)
44+
stop(msg)
4145
}
4246
)
4347
}
@@ -46,12 +50,13 @@ Paginator <- R6::R6Class("Paginator",
4650
client = NULL,
4751
request_type = NULL,
4852
get_page = function(request, start_index = 0, items_per_page = 10) {
49-
5053
req <- request
5154
if (private$request_type == "POST") {
5255
req <- req %>%
53-
httr2::req_body_json_modify(startIndex = start_index,
54-
itemsPerPage = items_per_page)
56+
httr2::req_body_json_modify(
57+
startIndex = start_index,
58+
itemsPerPage = items_per_page
59+
)
5560
} else {
5661
params <- list(
5762
startIndex = start_index,

R/search_results.R

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,45 +48,59 @@ SearchResults <- R6::R6Class("SearchResults",
4848
#' @param force Optional; forces the download even if the file already exists in the specified output directory.
4949
#' @param prompt Optional; enables all user prompts for decisions during file downloads. Defaults to true.
5050
#' @return Nothing returned but downloaded files are saved at the specified location.
51+
#' @importFrom progress progress_bar
5152
#' @export
5253
download = function(output_dir, selected_indexes, stop_at_failure = TRUE, force = FALSE, prompt = TRUE) {
5354
if (self$total_count == 0 || (prompt && !private$prompt_user_confirmation(self$total_size))) {
5455
return(NULL)
5556
}
5657

57-
message("[Download] Start")
58-
5958
if (!dir.exists(output_dir)) {
6059
dir.create(output_dir)
6160
}
6261

6362
resources_to_download <- if (missing(selected_indexes)) self$results else self$results[selected_indexes]
63+
64+
proggress_bar <- progress::progress_bar$new(
65+
format = "[Download] :current/:total (:percent) :elapsed",
66+
total = length(resources_to_download),
67+
clear = FALSE,
68+
width = 60
69+
)
70+
6471
i <- 0
65-
should_break <- FALSE
6672
for (r in resources_to_download) {
67-
if (should_break) {
68-
break
69-
}
70-
7173
i <- i + 1
7274

73-
message(paste0("[Download] Downloading file ", i, "/", length(resources_to_download)))
74-
7575
tryCatch(
7676
{
7777
download_id <- private$get_download_id(r)
7878
is_ready <- private$ensure_download_is_ready(download_id)
7979
if (is_ready) {
8080
private$download_resource(download_id, output_dir, force)
8181
}
82+
proggress_bar$tick()
8283
},
8384
error = function(err) {
84-
warning("Error during the downloading:", err, sep = "\n")
85-
should_break <<- stop_at_failure
85+
if (stop_at_failure) {
86+
proggress_bar$terminate()
87+
stop(conditionMessage(err))
88+
} else {
89+
err_msg <- conditionMessage(err)
90+
message(err_msg)
91+
92+
# Special handling for HTTP 429
93+
if (grepl("\\[HTTP 429\\]", err_msg)) {
94+
proggress_bar$terminate()
95+
stop(sprintf("Operation halted due to rate limit (HTTP 429). Please slow down your requests."))
96+
}
97+
98+
proggress_bar$message(conditionMessage(err))
99+
proggress_bar$tick()
100+
}
86101
}
87102
)
88103
}
89-
message("[Download] DONE")
90104
}
91105
),
92106
private = list(
@@ -132,7 +146,7 @@ SearchResults <- R6::R6Class("SearchResults",
132146

133147
# Check if the file already exists and force flag is FALSE
134148
if (file.exists(file_path) && !force) {
135-
warning("File already exists:", file_path, "- Skipping download.\n")
149+
# warning("File already exists:", file_path, "- Skipping download.\n")
136150
return(NA)
137151
}
138152

@@ -141,7 +155,12 @@ SearchResults <- R6::R6Class("SearchResults",
141155

142156
resp <- private$client$send_request(req, TRUE)
143157
if (resp$status_code != 200) {
144-
stop(paste("Couldn't download: ", url))
158+
stop(sprintf(
159+
"Failed to download data.\nURL: %s\nStatus code: %s\nReason: %s",
160+
url,
161+
resp$status_code,
162+
resp$status_text %||% "Unknown"
163+
))
145164
}
146165

147166
writeBin(httr2::resp_body_raw(resp), file_path)
@@ -150,7 +169,7 @@ SearchResults <- R6::R6Class("SearchResults",
150169
prompt_user_confirmation = function(total_size) {
151170
if (total_size >= private$LARGE_DOWNLOAD_SIZE) {
152171
repeat {
153-
message("The total size is ", humanize::natural_size(total_size), ". Do you want to proceed? (Y/N): ")
172+
message("The total size is ", scales::label_bytes()(total_size), ". Do you want to proceed? (Y/N): ")
154173
answer <- tolower(readLines(n = 1))
155174
if (answer %in% c("y", "n")) {
156175
return(answer == "y")
@@ -169,7 +188,12 @@ SearchResults <- R6::R6Class("SearchResults",
169188

170189
resp <- private$client$send_request(req, TRUE)
171190
if (resp$status_code != 200) {
172-
stop(paste("Couldn't download: ", url))
191+
stop(sprintf(
192+
"Failed to download data.\nURL: %s\nStatus code: %s\nReason: %s",
193+
url,
194+
resp$status_code,
195+
resp$status_text %||% "Unknown"
196+
))
173197
}
174198

175199
# Extract the file name from the Content-Disposition header

R/utils.R

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,68 @@ strip_off_template_placeholders <- function(template) {
124124
is_single_string <- function(input) {
125125
is.character(input) & length(input) == 1
126126
}
127+
128+
format_error_message <- function(
129+
err,
130+
context = "Operation failed",
131+
include_url = TRUE,
132+
fallback_status = "Unknown") {
133+
134+
if (is.null(err)) {
135+
return("Unknown Network Error")
136+
}
137+
138+
if (!is.null(err) && inherits(err, "httr2_response")) {
139+
resp <- err
140+
parsed <- tryCatch(httr2::resp_body_json(resp), error = function(e) NULL)
141+
142+
# Try to parse the 'detail' field to extract error's metadata
143+
parsed_detail <- NULL
144+
if (!is.null(parsed$detail) && is.character(parsed$detail) && grepl("^\\s*\\{", parsed$detail)) {
145+
parsed_detail <- tryCatch(jsonlite::fromJSON(parsed$detail), error = function(e) NULL)
146+
}
147+
148+
top_status <- parsed$status_code %||% httr2::resp_status(resp) %||% fallback_status
149+
top_title <- parsed$title %||% "Unspecified error"
150+
top_url <- parsed$url %||% NULL
151+
152+
nested_status <- parsed_detail$status_code %||% NULL
153+
nested_title <- parsed_detail$title %||% NULL
154+
nested_detail_text <- parsed_detail$detail %||% ""
155+
156+
msg_match <- regmatches(nested_detail_text, regexpr("message='([^']+)'", nested_detail_text))
157+
url_match <- regmatches(nested_detail_text, regexpr("url='([^']+)'", nested_detail_text))
158+
159+
extracted_message <- NA
160+
if (length(msg_match) == 1 && grepl("message='[^']+'", msg_match)) {
161+
extracted_message <- sub("message='([^']+)'", "\\1", msg_match)
162+
}
163+
164+
extracted_url <- NA
165+
if (length(url_match) == 1 && grepl("url='[^']+'", url_match)) {
166+
extracted_url <- sub("url='([^']+)'", "\\1", url_match)
167+
}
168+
169+
final_title <- nested_title %||% top_title
170+
final_status <- nested_status %||% top_status
171+
172+
message <- sprintf("%s [HTTP %s]: %s", context, final_status, final_title)
173+
174+
if (!is.null(extracted_message) && !is.na(extracted_message) && nzchar(extracted_message)) {
175+
message <- paste0(message, "\nDetail: ", extracted_message)
176+
}
177+
178+
if (include_url && !is.null(extracted_url) && !is.na(extracted_url) &&nzchar(extracted_url)) {
179+
message <- paste0(message, "\nURL: ", extracted_url)
180+
}
181+
182+
return(message)
183+
}
184+
185+
186+
# Fallback to base condition message
187+
msg <- conditionMessage(err)
188+
first_line <- strsplit(msg, "\n")[[1]][1]
189+
sprintf("%s: %s", context, first_line)
190+
}
191+

R/zzz.R

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
#' @importFrom utils packageVersion
2+
NULL
3+
14
.onAttach <- function(libname, pkgname) {
25
# Get the package version
3-
#' @importFrom utils packageVersion
4-
version <- packageVersion(pkgname)
6+
version <- utils::packageVersion(pkgname)
57
# Console message for additional information
68
packageStartupMessage(paste(pkgname, version, "\n"))
79
}

0 commit comments

Comments
 (0)