diff --git a/DESCRIPTION b/DESCRIPTION index 343db09..1fe16c9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -33,6 +33,7 @@ Imports: Suggests: testthat (>= 3.0.0), htmltools, + htmlwidgets, knitr, magick, rmarkdown, diff --git a/NAMESPACE b/NAMESPACE index 8686b4b..3278eae 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -124,6 +124,7 @@ export(get_and_start_cluster) export(get_and_start_warehouse) export(get_latest_dbr) export(git_source) +export(in_databricks_nb) export(init_script_info) export(is.access_control_req_group) export(is.access_control_req_user) @@ -168,7 +169,9 @@ export(lib_pypi) export(lib_whl) export(libraries) export(new_cluster) +export(notebook_enable_htmlwidgets) export(notebook_task) +export(notebook_use_posit_repo) export(open_workspace) export(pipeline_task) export(python_wheel_task) diff --git a/R/brickster.R b/R/brickster.R new file mode 100644 index 0000000..26243a7 --- /dev/null +++ b/R/brickster.R @@ -0,0 +1 @@ +utils::globalVariables(c("displayHTML")) diff --git a/R/notebook-helpers.R b/R/notebook-helpers.R new file mode 100644 index 0000000..8fdfa62 --- /dev/null +++ b/R/notebook-helpers.R @@ -0,0 +1,91 @@ +#' Detect if running within Databricks Notebook +#' +#' @details +#' R sessions on Databricks can be detected via various environment variables +#' and directories. +#' +#' @return Boolean +#' @export +in_databricks_nb <- function() { + ("/databricks/spark/R/lib" %in% .libPaths()) && + exists("DATABRICKS_GUID", envir = .GlobalEnv) +} + +#' Setup Databricks Notebook with Posit Package Manager +#' +#' @details +#' Databricks notebooks default repo for package installation is CRAN. +#' CRAN doesn't provide pre-compiled binaries for linux and this results in +#' packages taking longer than desired. +#' +#' This function can be called within a Databricks notebook to easily switch to +#' Posit and retrieve pre-compiled binaries. +#' +#' This function will behave correctly across different Databricks Runtimes, +#' even when the underlying linux version changes. +#' +#' @export +notebook_use_posit_repo <- function() { + if (in_databricks_nb()) { + agent <- sprintf("R/%s R (%s)", getRversion(), paste(getRversion(), R.version["platform"], R.version["arch"], R.version["os"])) + codename <- system("lsb_release -c --short", intern = T) + mirror <- paste0("https://packagemanager.posit.co/cran/__linux__/", codename, "/latest") + options( + HTTPUserAgent = agent, + repos = c(POSIT = mirror, getOption("repos")) + ) + } +} + +#' Enable htmlwidgets in Databricks Notebook +#' +#' @details +#' Databricks notebooks by default don't currently support htmlwidgets. +#' This behaviour can be corrected by: +#' - adjusting the print method in htmltools +#' - installing pandoc +#' +#' This is a invasive method to correct the behaviour as htmltools isn't +#' flexible to adjust via the `viewer` option directly. +#' +#' It only runs within a Databricks notebook cell. +#' +#' The height can be adjusted without running the function again by using the +#' `db_htmlwidget_height` option (e.g. `options(db_htmlwidget_height = 300)`). +#' +#' +#' @param height Measurement passed to height of htmlwidget. This overrides +#' existing values that may often be `NULL` to ensure the height is correctly +#' displayed within the iframe of notebook results cells (via `displayHTML()`). +#' Default is 450. +#' +#' @export +#' +#' @examples +#' notebook_enable_htmlwidgets() +#' # set default height to 800px +#' notebook_enable_htmlwidgets(height = 800) +notebook_enable_htmlwidgets <- function(height = 450) { + if (in_databricks_nb()) { + + # new option to control default widget height, default is 450px + options(db_htmlwidget_height = height) + + system("apt-get --yes install pandoc", intern = T) + if (!base::require("htmlwidgets")) { + utils::install.packages("htmlwidgets") + } + + # new method will fetch height based on new option, or default to 450px + new_method <- function(x, ...) { + x$height <- getOption("db_htmlwidget_height", 450) + file <- tempfile(fileext = ".html") + htmlwidgets::saveWidget(x, file = file) + contents <- as.character(rvest::read_html(file)) + displayHTML(contents) + } + + utils::assignInNamespace("print.htmlwidget", new_method, ns = "htmlwidgets") + invisible(list(default_height = height, print = new_method)) + } +} diff --git a/_pkgdown.yml b/_pkgdown.yml index fa466a1..47559c7 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -49,6 +49,11 @@ reference: contents: - starts_with("db_libs", internal = TRUE) - wait_for_lib_installs +- title: Databricks Notebook Helpers + contents: + - in_databricks_nb + - notebook_use_posit_repo + - notebook_enable_htmlwidgets - title: DBFS contents: starts_with("db_dbfs", internal = TRUE) - title: Volume FileSystem diff --git a/man/in_databricks_nb.Rd b/man/in_databricks_nb.Rd new file mode 100644 index 0000000..6390aa8 --- /dev/null +++ b/man/in_databricks_nb.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/notebook-helpers.R +\name{in_databricks_nb} +\alias{in_databricks_nb} +\title{Detect if running within Databricks Notebook} +\usage{ +in_databricks_nb() +} +\value{ +Boolean +} +\description{ +Detect if running within Databricks Notebook +} +\details{ +R sessions on Databricks can be detected via various environment variables +and directories. +} diff --git a/man/notebook_enable_htmlwidgets.Rd b/man/notebook_enable_htmlwidgets.Rd new file mode 100644 index 0000000..a74bb7d --- /dev/null +++ b/man/notebook_enable_htmlwidgets.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/notebook-helpers.R +\name{notebook_enable_htmlwidgets} +\alias{notebook_enable_htmlwidgets} +\title{Enable htmlwidgets in Databricks Notebook} +\usage{ +notebook_enable_htmlwidgets(height = 450) +} +\arguments{ +\item{height}{Measurement passed to height of htmlwidget. This overrides +existing values that may often be \code{NULL} to ensure the height is correctly +displayed within the iframe of notebook results cells (via \code{displayHTML()}). +Default is 450.} +} +\description{ +Enable htmlwidgets in Databricks Notebook +} +\details{ +Databricks notebooks by default don't currently support htmlwidgets. +This behaviour can be corrected by: +\itemize{ +\item adjusting the print method in htmltools +\item installing pandoc +} + +This is a invasive method to correct the behaviour as htmltools isn't +flexible to adjust via the \code{viewer} option directly. + +It only runs within a Databricks notebook cell. + +The height can be adjusted without running the function again by using the +\code{db_htmlwidget_height} option (e.g. \code{options(db_htmlwidget_height = 300)}). +} +\examples{ +notebook_enable_htmlwidgets() +# set default height to 800px +notebook_enable_htmlwidgets(height = 800) +} diff --git a/man/notebook_use_posit_repo.Rd b/man/notebook_use_posit_repo.Rd new file mode 100644 index 0000000..c5d88fb --- /dev/null +++ b/man/notebook_use_posit_repo.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/notebook-helpers.R +\name{notebook_use_posit_repo} +\alias{notebook_use_posit_repo} +\title{Setup Databricks Notebook with Posit Package Manager} +\usage{ +notebook_use_posit_repo() +} +\description{ +Setup Databricks Notebook with Posit Package Manager +} +\details{ +Databricks notebooks default repo for package installation is CRAN. +CRAN doesn't provide pre-compiled binaries for linux and this results in +packages taking longer than desired. + +This function can be called within a Databricks notebook to easily switch to +Posit and retrieve pre-compiled binaries. + +This function will behave correctly across different Databricks Runtimes, +even when the underlying linux version changes. +} diff --git a/tests/testthat/test-connection-pane.R b/tests/testthat/test-connection-pane.R index 66da7d5..02299ae 100644 --- a/tests/testthat/test-connection-pane.R +++ b/tests/testthat/test-connection-pane.R @@ -113,12 +113,15 @@ test_that("Connection Pane Helpers", { host = db_host(), token = db_token() ) + # remove serverless clusters from test as they cause an issue + clusters <- clusters[!grepl("v2n", clusters$name), ] cluster_id <- get_id_from_panel_name(clusters$name[[1]]) cluster_data <- get_cluster( id = cluster_id, host = db_host(), token = db_token() ) + }) expect_type(clusters, "list") expect_type(cluster_data, "list") diff --git a/tests/testthat/test-notebook-helpers.R b/tests/testthat/test-notebook-helpers.R new file mode 100644 index 0000000..169c402 --- /dev/null +++ b/tests/testthat/test-notebook-helpers.R @@ -0,0 +1,8 @@ +test_that("Databricks Notebook Helpers", { + + # currently running tests outside of a databricks notebook + expect_false(in_databricks_nb()) + expect_no_error(notebook_use_posit_repo()) + expect_no_error(notebook_enable_htmlwidgets()) + +})