Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: format errors #21

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b2e354f
feat: now print errors if specified by option
timcadman Apr 30, 2024
a7ceaf9
fix: now only return message if error
timcadman Apr 30, 2024
e4f1846
chore: tests for assign expression
timcadman May 8, 2024
6039d56
feat: improved formatting
timcadman May 8, 2024
b4ab7b4
chore: added error handling to assign table and resource
timcadman May 8, 2024
16fb161
chore: updated dependencies
timcadman May 9, 2024
cb6c8fa
chore: updated docs
timcadman May 9, 2024
2493a40
chore: updated docs and added dependencies
timcadman May 9, 2024
3438f95
chore: added missing arguments and updated dependencies
timcadman May 9, 2024
2a963f0
feat: vary formatting depending on whether called within datashield.a…
timcadman Jun 17, 2024
0571651
feat: now return an error rather than warning
timcadman Jun 17, 2024
9e4ab36
feat: format .checkLastErrors in same style as datashield.errors
timcadman Jun 17, 2024
7e14637
return simpler error to avoid duplication
timcadman Jun 17, 2024
5cf8104
test: now test calling external script
timcadman Jun 17, 2024
78b2476
tidied up to pass check
timcadman Jun 17, 2024
c299047
fix: don't return error message if no errors
timcadman Jun 17, 2024
c428576
test: added test for no error scenario
timcadman Jun 17, 2024
790fee3
docs: align error message whether error returned direction or via dat…
timcadman Jul 4, 2024
6235bf3
feat: add cohort names into errors and format with nice colour
timcadman Jul 4, 2024
371a5d0
chore: added .DS_Store to ignores
timcadman Jul 4, 2024
023df34
test: test for more specific message and fixed broken test
timcadman Jul 4, 2024
6462ef9
chore: removed unnecessary dependencies
timcadman Jul 4, 2024
08e9f1c
chore: rm ds_store
timcadman Jul 4, 2024
84f9c62
fix: corrected direction of curly bracket
timcadman Jul 4, 2024
75bdc10
Merge branch 'master' into feat/format-errors
timcadman Jul 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
timcadman marked this conversation as resolved.
Show resolved Hide resolved
Binary file not shown.
12 changes: 9 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,20 @@ Depends:
R (>= 3.1),
methods,
progress,
R6
R6,
Imports:
cli,
dplyr,
purrr,
stringr
Suggests:
testthat (>= 2.1.0)
testthat (>= 2.1.0),
DSLite
License: LGPL (>= 2.1)
URL: https://github.com/datashield/DSI/,
https://datashield.github.io/DSI/, https://datashield.org/
BugReports: https://github.com/datashield/DSI/issues
RoxygenNote: 7.2.1
RoxygenNote: 7.3.1
Encoding: UTF-8
Collate:
'DSObject.R'
Expand Down
7 changes: 7 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,10 @@ exportClasses(DSResult)
import(R6)
import(methods)
import(progress)
importFrom(cli,cli_abort)
importFrom(cli,cli_alert_warning)
importFrom(cli,cli_bullets)
importFrom(dplyr,"%>%")
importFrom(purrr,imap_chr)
importFrom(purrr,map)
importFrom(stringr,str_replace_all)
153 changes: 89 additions & 64 deletions R/datashield.assign.R

Large diffs are not rendered by default.

57 changes: 53 additions & 4 deletions R/datashield.errors.R
Original file line number Diff line number Diff line change
@@ -1,13 +1,62 @@
#' List R last errors
#' datashield.errors
#'
#' Get the R last errors available after the datashield.assign or datashield.aggregate calls in the Datashield R session.
#' Retrieve and display the last errors occurred in a DataSHIELD session.
#'
#' This function retrieves the last errors occurred in a DataSHIELD session
#' and displays them in a formatted manner using bullet points.
#'
#' @param type Specify format for return message. If type == "message", a formatted message is
#' returned. If type == "assign" a named vector is returned which will be formatted and returned
#' within datashield.assign.
#' @return NULL if no errors are found, otherwise prints the errors.
#' @importFrom cli cli_bullets
#' @export
datashield.errors <- function() {
datashield.errors <- function(type = "message") {
env <- getOption("datashield.env", globalenv())
if (exists(".datashield.last_errors", envir = env)) {
get(".datashield.last_errors", envir = env)
errors <- get(".datashield.last_errors", envir = env)
neat <- .format_errors(errors)
if(type == "assign") {
return(neat)
} else if(type == "message"){
cli_bullets(neat)
}

} else {
NULL
}
}

#' Format Errors
#'
#' Format errors into a character vector with specified prefix.
#'
#' This function formats a list of errors into a character vector with each
#' error message prefixed by a cross.
#'
#' @param errors A list of errors to be formatted.
#' @return A character vector containing formatted error messages.
#' @importFrom dplyr %>%
#' @importFrom purrr imap_chr
#' @importFrom stringr str_replace_all
#' @noRd
.format_errors <- function(errors){
no_brackets <- .remove_curly_brackets(errors)
errors <- unlist(no_brackets)
names(errors) <- rep("x", length(errors))
return(errors)
}

#' Remove Curly Brackets from Strings
#'
#' This function replaces all curly brackets in the input strings with parentheses.
#'
#' @param errors A list of strings that may contain curly brackets.
#' @return A list of strings with curly brackets replaced by parentheses.
#' @importFrom purrr map
#' @importFrom stringr str_replace_all
.remove_curly_brackets <- function(errors) {
errors <- errors %>% map(~str_replace_all(.x, "\\{", "("))
timcadman marked this conversation as resolved.
Show resolved Hide resolved
errors <- errors %>% map(~str_replace_all(.x, "\\}", ")"))
return(errors)
}
5 changes: 3 additions & 2 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,14 @@
}

#' Check if there are last errors
#' @importFrom cli cli_abort cli_alert_warning
#' @keywords internal
.checkLastErrors <- function(env=getOption("datashield.env", globalenv())) {
if (exists(".datashield.last_errors", envir = env)) {
if (getOption("datashield.errors.stop", TRUE)) {
stop("There are some DataSHIELD errors, list them with datashield.errors()", call. = FALSE)
cli_abort("There are some DataSHIELD errors, list them with datashield.errors()", call = NULL)
} else {
warning("There are some DataSHIELD errors, list them with datashield.errors()", call. = FALSE)
cli_alert_warning("There are some DataSHIELD errors, list them with datashield.errors()")
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions man/datashield.assign.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions man/datashield.assign.expr.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions man/datashield.assign.resource.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 10 additions & 7 deletions man/datashield.assign.table.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/datashield.connections_default.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/datashield.connections_find.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 15 additions & 3 deletions man/datashield.errors.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions man/dot-remove_curly_brackets.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 59 additions & 0 deletions tests/testthat/test-assign.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
library(DSLite)
library(testthat)
library(dplyr)
library(stringr)

options(datashield.env = environment())
data("mtcars")
dslite.server <- DSLite::newDSLiteServer(tables = list(mtcars = mtcars))
data("logindata.dslite.cnsim")
logindata.dslite.cnsim <- logindata.dslite.cnsim %>%
mutate(table = "mtcars")
dslite.server$config(defaultDSConfiguration(include = c("dsBase", "dsTidyverse", "dsDanger")))
dslite.server$assignMethod("selectDS", "selectDS")
dslite.server$aggregateMethod("exists", "base::exists")
dslite.server$aggregateMethod("classDS", "dsBase::classDS")
dslite.server$aggregateMethod("lsDS", "dsBase::lsDS")
conns <- datashield.login(logins = logindata.dslite.cnsim, assign = TRUE)

## ---- Assign expression --------------------------------------------------------------------------
test_that("datashield.assign.expr returns 'datashield error' message when datashield.return_errors = FALSE", {
options("datashield.return_errors" = FALSE)
expect_error(
datashield.assign.expr(conns, symbol = "G", expr = "doesntwork"),
"There are some DataSHIELD errors, list them with datashield.errors()"
)
})

test_that("datashield.assign.expr returns message when datashield.return_errors = TRUE", {
options("datashield.return_errors" = TRUE)
expect_error(
datashield.assign.expr(conns, symbol = "G", expr = "doesntwork"),
)
})

test_that("datashield.assign.expr throws error if external script called", {
options("datashield.return_errors" = TRUE)
expect_error(
source("testdata/r-fail-loop.R")
)
})

test_that("datashield.assign.expr throws error if external script called", {
options("datashield.return_errors" = FALSE)
expect_error(
source("testdata/r-fail-loop.R")
)
})

test_that("datashield.assign.expr doesn't return errors if there aren't any", {
cally <- call("absDS", 10)
options("datashield.return_errors" = FALSE)
expect_silent(
datashield.assign.expr(conns, symbol = "new_obj", expr = cally)
)
options("datashield.return_errors" = TRUE)
expect_silent(
datashield.assign.expr(conns, symbol = "new_obj", expr = cally)
)
})
Loading