diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 495e6cbc..60860342 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -27,7 +27,7 @@ jobs: - uses: r-lib/actions/setup-r@v2 with: use-public-rspm: true - extra-repositories: https://mrc-ide.r-universe.dev/bin/linux/jammy/4.3 + extra-repositories: https://mrc-ide.r-universe.dev - uses: r-lib/actions/setup-r-dependencies@v2 with: diff --git a/DESCRIPTION b/DESCRIPTION index 09c749cb..f84e736a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -26,7 +26,6 @@ Imports: brio, data.tree, dplyr (>= 1.1.0), - duckdb (>= 0.10.0), eppasm (>= 0.7.1), gt, first90 (>= 1.6.1), @@ -60,6 +59,7 @@ Suggests: DiagrammeR, covr, datamodelr, + duckdb (>= 0.10.0), here, knitr, lubridate, diff --git a/NEWS.md b/NEWS.md index fe62db41..313bac38 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# naomi 2.9.28 + +* Make duckdb an optional dependency + # naomi 2.9.27 * Show calibration plot ratio values to nearest 0.1. diff --git a/R/outputs.R b/R/outputs.R index 3e2ebdec..40485f1d 100644 --- a/R/outputs.R +++ b/R/outputs.R @@ -1355,6 +1355,7 @@ read_hintr_output <- function(path) { } read_duckdb <- function(path) { + assert_package_installed("duckdb") con <- DBI::dbConnect(duckdb::duckdb(dbdir = path, read_only = TRUE)) on.exit(DBI::dbDisconnect(con, shutdown = TRUE)) DBI::dbGetQuery(con, sprintf("SELECT * from %s", DUCKDB_OUTPUT_TABLE_NAME)) diff --git a/R/run-model.R b/R/run-model.R index 85965d1c..3ffeacab 100644 --- a/R/run-model.R +++ b/R/run-model.R @@ -157,6 +157,7 @@ hintr_save <- function(obj, file) { stop(paste("Trying to save invalid object as duckdb database.", "Only data frames can be saved as database.")) } + assert_package_installed("duckdb") con <- DBI::dbConnect(duckdb::duckdb(dbdir = file)) on.exit(DBI::dbDisconnect(con, shutdown = TRUE)) DBI::dbWriteTable(con, DUCKDB_OUTPUT_TABLE_NAME, obj) diff --git a/R/utils.R b/R/utils.R index 6662f84c..528c1787 100644 --- a/R/utils.R +++ b/R/utils.R @@ -100,3 +100,15 @@ vlapply <- function(X, FUN, ...) { is_empty <- function(x) { length(x) == 0 || is.null(x) || is.na(x) || !nzchar(x) } + + +assert_package_installed <- function(package_name) { + if (!requireNamespace(package_name, quietly = TRUE)) { + stop( + sprintf("Package '%s' must be installed to use this function.", + package_name), + call. = FALSE + ) + } + invisible(TRUE) +} diff --git a/tests/testthat/test-01-run-model.R b/tests/testthat/test-01-run-model.R index 8bdbb9bd..a93d3d68 100644 --- a/tests/testthat/test-01-run-model.R +++ b/tests/testthat/test-01-run-model.R @@ -689,6 +689,7 @@ test_that("trying to calibrate incompatible model output returns error", { }) test_that("calibration plot data can be saved as duckdb database", { + testthat::skip_if_not_installed("duckdb") ## Calibration makes no modification of existing files. output_hash <- tools::md5sum(a_hintr_output$model_output_path) diff --git a/tests/testthat/test-hintr-plot-data.R b/tests/testthat/test-hintr-plot-data.R index cf5370df..1e771e34 100644 --- a/tests/testthat/test-hintr-plot-data.R +++ b/tests/testthat/test-hintr-plot-data.R @@ -54,6 +54,8 @@ test_that("there is metadata for every indicator in comparison data", { }) test_that("hintr data can be saved and read as qs or duckdb type", { + testthat::skip_if_not_installed("duckdb") + t_qs <- tempfile(fileext = ".qs") t_db <- tempfile(fileext = ".duckdb") t_rds <- tempfile(fileext = ".rds") diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R index 96af513f..e8410cd8 100644 --- a/tests/testthat/test-utils.R +++ b/tests/testthat/test-utils.R @@ -26,3 +26,12 @@ test_that("is_empty", { expect_true(is_empty(c())) expect_false(is_empty(c("things"))) }) + +test_that("can assert optional package is installed", { + expect_true(assert_package_installed("testthat")) + + expect_error( + assert_package_installed("my.fake.pkg"), + "Package 'my.fake.pkg' must be installed to use this function.", + fixed = TRUE) +})