From f2b934ac0a126520b25a7431206b5109acf52c1f Mon Sep 17 00:00:00 2001 From: Fran Barton Date: Fri, 17 Jul 2026 16:26:03 +0100 Subject: [PATCH] :yo_yo: Handle lookups from GitHub via direct URLs Should close #162 --- R/get_github_file.R | 72 +++++++++++++++++------------------- R/get_principal_pods.R | 36 +++++------------- R/helpers.R | 56 +++++++++++++++------------- man/convert_activity_type.Rd | 18 +++++++++ man/get_detailed_pods.Rd | 14 ++----- man/get_outputs_gh_file.Rd | 21 ----------- man/get_outputs_gh_url.Rd | 15 ++++++++ man/get_su_gh_file.Rd | 23 ++++++++++++ man/get_tpma_label_lookup.Rd | 14 ++----- man/get_tpmas_gh_file.Rd | 21 ----------- man/get_tpmas_gh_url.Rd | 15 ++++++++ man/read_pods_lookup.Rd | 11 ++++++ man/read_tpmas_lookup.Rd | 11 ++++++ 13 files changed, 172 insertions(+), 155 deletions(-) create mode 100644 man/convert_activity_type.Rd delete mode 100644 man/get_outputs_gh_file.Rd create mode 100644 man/get_outputs_gh_url.Rd create mode 100644 man/get_su_gh_file.Rd delete mode 100644 man/get_tpmas_gh_file.Rd create mode 100644 man/get_tpmas_gh_url.Rd create mode 100644 man/read_pods_lookup.Rd create mode 100644 man/read_tpmas_lookup.Rd diff --git a/R/get_github_file.R b/R/get_github_file.R index ef8eebe..8f10699 100644 --- a/R/get_github_file.R +++ b/R/get_github_file.R @@ -1,48 +1,42 @@ -#' Read in a file from the NHP Outputs app GitHub repo +#' Get the direct URL to a file in the NHP Outputs GitHub repo #' -#' @param file string. The name of the file to read in -#' @param folder string. The folder where the file is located. `"inst"` by -#' default. Set to `""` to use the root folder of the repo. -#' @returns The file contents as a stream, to be passed to a reader function +#' @param ... Pass the name of the file in via `...` #' @keywords internal -get_outputs_gh_file <- function(file, folder = "inst") { - httr2::request("https://api.github.com") |> - httr2::req_url_path_append("repos") |> - httr2::req_url_path_append("The-Strategy-Unit") |> - httr2::req_url_path_append("nhp_outputs") |> - httr2::req_url_path_append("contents") |> - httr2::req_url_path_append(folder) |> - httr2::req_url_path_append(file) |> - httr2::req_perform() |> - httr2::resp_check_status() |> - httr2::resp_body_json() |> - purrr::pluck("content") |> - base64enc::base64decode() +get_outputs_gh_url <- function(...) { + purrr::partial(get_su_gh_file, repo = "nhp_outputs", folder = "inst")(...) } - -#' Read in a file from the TPMAs GitHub repo +#' Get the direct URL to a file in the TPMAs GitHub repo #' -#' @param file string. The name of the file to read in -#' @param folder string. The folder where the file is located. `"reference"` by -#' default. Set to `""` to use the root folder of the repo. -#' @returns The file contents as a stream, to be passed to a reader function +#' @inheritParams get_outputs_gh_url #' @keywords internal -get_tpmas_gh_file <- function(file, folder = "reference") { - httr2::request("https://api.github.com") |> - httr2::req_url_path_append("repos") |> - httr2::req_url_path_append("The-Strategy-Unit") |> - httr2::req_url_path_append("TPMAs") |> - httr2::req_url_path_append("contents") |> - httr2::req_url_path_append(folder) |> - httr2::req_url_path_append(file) |> - httr2::req_perform() |> - httr2::resp_check_status() |> - httr2::resp_body_json() |> - purrr::pluck("content") |> - base64enc::base64decode() +get_tpmas_gh_url <- function(...) { + purrr::partial(get_su_gh_file, repo = "TPMAs", folder = "reference")(...) } +#' Read the pods lookup table from a YAML file in the NHP Outputs repo +read_pods_lookup <- function(file = "golem-config.yml") { + yaml12::parse_yaml(readr::read_lines(get_outputs_gh_url(file))) +} +possibly_read_pods_lookup <- \(...) purrr::possibly(read_pods_lookup)(...) + +#' Read the TPMAs lookup table from a CSV file in the TPMAs repo +read_tpmas_lookup <- function(file = "tpma-lookup.csv") { + readr::read_csv(get_tpmas_gh_url(file), col_types = "-ccccc---c") +} +possibly_read_tpmas_lookup <- \(...) purrr::possibly(read_tpmas_lookup)(...) -possibly_get_outputs_gh_file <- \(...) purrr::possibly(get_outputs_gh_file)(...) -possibly_get_tpmas_gh_file <- \(...) purrr::possibly(get_tpmas_gh_file)(...) + +#' Read in a file from a Strategy Unit GitHub repo +#' +#' @param repo string. The name of the repository in which to find the file +#' @param folder string. The folder where the file is located. Set to `""` to +#' use the root folder of the repo. +#' @param file string. The name of the file to read in +#' @returns The URL to the raw file contents, to be passed to a reader function +#' @keywords internal +get_su_gh_file <- function(repo, folder, file) { + raw_base_url <- "https://raw.githubusercontent.com" + su <- "The-Strategy-Unit" + file.path(raw_base_url, su, repo, "refs", "heads", "main", folder, file) +} diff --git a/R/get_principal_pods.R b/R/get_principal_pods.R index 0adb092..6e8b315 100644 --- a/R/get_principal_pods.R +++ b/R/get_principal_pods.R @@ -1,35 +1,19 @@ #' Prepare a lookup table with activity type labels and PoD labels for each PoD #' -#' @param use_local logical. Whether to use a local file (internal to the -#' reskit package) or attempt to pull the lookup file from GitHub. Default is -#' `FALSE`, meaning it will use the GitHub route. If you want to always use a -#' local file (for example, for fully offline working), you can set the -#' `reskit.local.lookups` option to `TRUE` using -#' `options(reskit.local.lookups = TRUE)` or `withr::with_options()` #' @returns A tibble #' @export -get_detailed_pods <- function(use_local = FALSE) { - use_local <- getOption("reskit.local.lookups") %||% use_local - yaml_data <- system.file("pod_measures.yml", package = "reskit") |> - yaml12::read_yaml() - yaml_data_from_gh <- NULL - if (!use_local) { - yaml_raw <- possibly_get_outputs_gh_file("golem-config.yml") - if (!is.null(yaml_raw)) { - yaml_data_from_gh <- yaml12::parse_yaml(readr::read_lines(yaml_raw)) |> - purrr::pluck("default") - } - } - yaml_data <- yaml_data_from_gh %||% yaml_data +get_detailed_pods <- function() { + yaml_data <- possibly_read_pods_lookup() + msg <- "Unable to read POD lookup file from GitHub" + azkit::check_that(yaml_data, is_not_null, msg) yaml_data |> - purrr::pluck("pod_measures") |> + purrr::pluck("default", "pod_measures") |> purrr::map(list_to_tbl) |> purrr::list_rbind() |> dplyr::mutate( dplyr::across("pod_label", forcats::fct_inorder), - dplyr::across("activity_type_label", \(x) sub("patients$", "patient", x)), dplyr::across("activity_type_label", \(x) { - forcats::fct(x, levels = c("Inpatient", "Outpatient", "A&E")) + forcats::fct(x, levels = c("Inpatients", "Outpatients", "A&E")) }) ) } @@ -38,12 +22,12 @@ get_detailed_pods <- function(use_local = FALSE) { #' Prepare a lookup table with activity type labels and PoD labels for each PoD #' #' This function condenses all A&E activity to a single category - compare -#' `get_detailed_pods()` which _keeps_ all A&E categories +#' [get_detailed_pods] which _keeps_ all A&E categories #' @rdname get_detailed_pods #' @returns A tibble #' @export -get_principal_pods <- function(use_local = FALSE) { - get_detailed_pods(use_local) |> +get_principal_pods <- function() { + get_detailed_pods() |> dplyr::filter(dplyr::if_any("activity_type_label", \(x) x != "A&E")) |> dplyr::add_row( activity_type_label = "A&E", @@ -53,7 +37,7 @@ get_principal_pods <- function(use_local = FALSE) { dplyr::mutate( dplyr::across("pod_label", forcats::fct_inorder), dplyr::across("activity_type_label", \(x) { - forcats::fct(x, levels = c("Inpatient", "Outpatient", "A&E")) + forcats::fct(x, levels = c("Inpatients", "Outpatients", "A&E")) }) ) } diff --git a/R/helpers.R b/R/helpers.R index 30b29c9..d39119d 100644 --- a/R/helpers.R +++ b/R/helpers.R @@ -177,36 +177,37 @@ get_tretspef_lookup <- function() { #' Prepare a lookup table for all current TPMAs #' -#' @param use_local logical. Whether to use a local file (internal to the -#' reskit package) or attempt to pull the lookup file from GitHub. Default is -#' `FALSE`, meaning it will use the GitHub route. If you want to always use a -#' local file (for example, for fully offline working), you can set the -#' `reskit.local.lookups` option to `TRUE` using -#' `options(reskit.local.lookups = TRUE)` or `withr::with_options()` -#' @returns A 4-column tibble, with columns `activity_type`, `change_factor`, -#' `strategy` and `tpma_label` +#' @returns A 4-column tibble, with columns `strategy`, `activity_type`, +#' `change_factor` and `tpma_label` #' @export -get_tpma_label_lookup <- function(use_local = FALSE) { - read_cols <- "cccc----c" - use_local <- getOption("reskit.local.lookups") %||% use_local - csv_data <- system.file("mitigator-lookup.csv", package = "reskit") |> - readr::read_csv(col_types = read_cols) - csv_data_from_gh <- NULL - if (!use_local) { - csv_data_raw <- possibly_get_tpmas_gh_file("mitigator-lookup.csv") - if (!is.null(csv_data_raw)) { - csv_data_from_gh <- readr::read_csv(csv_data_raw, col_types = read_cols) - } - } - csv_data <- csv_data_from_gh %||% csv_data +get_tpma_label_lookup <- function() { + csv_data <- possibly_read_tpmas_lookup() + msg <- "Unable to read TPMA lookup table from GitHub" + azkit::check_that(csv_data, is_not_null, msg) csv_data |> dplyr::filter(dplyr::if_any("active_to", is.na)) |> dplyr::select(!"active_to") |> - dplyr::rename( - change_factor = "mitigator_type", - strategy = "mitigator_variable", - tpma_label = "mitigator_name" - ) + dplyr::mutate( + tpma_label = glue::glue("{tpma_name} ({tpma_subtype})"), + dplyr::across("tpma_type", \(x) tolower(sub(" ", "_", x))), + dplyr::across("activity_type", convert_activity_type), + .keep = "unused" + ) |> + dplyr::rename(change_factor = "tpma_type", strategy = "tpma_variable") +} + + +#' Converts "In|Outpatients", "A&E" strings to "ip", "op" and "aae" +#' @param x A character vector +#' @returns A character vector +#' @keywords internal +convert_activity_type <- function(x) { + dplyr::recode_values( + x, + "A&E" ~ "aae", + "Inpatients" ~ "ip", + "Outpatients" ~ "op" + ) } @@ -216,3 +217,6 @@ get_tpma_label_lookup <- function(use_local = FALSE) { #' @returns A character vector: all values of x that match the regex in rx #' @keywords internal gregv <- \(x, rx, g = parent.frame()) grepv(glue::glue_data(g, rx), x) + + +is_not_null <- \(x) !is.null(x) diff --git a/man/convert_activity_type.Rd b/man/convert_activity_type.Rd new file mode 100644 index 0000000..8da2073 --- /dev/null +++ b/man/convert_activity_type.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/helpers.R +\name{convert_activity_type} +\alias{convert_activity_type} +\title{Converts "In|Outpatients", "A&E" strings to "ip", "op" and "aae"} +\usage{ +convert_activity_type(x) +} +\arguments{ +\item{x}{A character vector} +} +\value{ +A character vector +} +\description{ +Converts "In|Outpatients", "A&E" strings to "ip", "op" and "aae" +} +\keyword{internal} diff --git a/man/get_detailed_pods.Rd b/man/get_detailed_pods.Rd index a28d98a..0d029da 100644 --- a/man/get_detailed_pods.Rd +++ b/man/get_detailed_pods.Rd @@ -5,17 +5,9 @@ \alias{get_principal_pods} \title{Prepare a lookup table with activity type labels and PoD labels for each PoD} \usage{ -get_detailed_pods(use_local = FALSE) +get_detailed_pods() -get_principal_pods(use_local = FALSE) -} -\arguments{ -\item{use_local}{logical. Whether to use a local file (internal to the -reskit package) or attempt to pull the lookup file from GitHub. Default is -\code{FALSE}, meaning it will use the GitHub route. If you want to always use a -local file (for example, for fully offline working), you can set the -\code{reskit.local.lookups} option to \code{TRUE} using -\code{options(reskit.local.lookups = TRUE)} or \code{withr::with_options()}} +get_principal_pods() } \value{ A tibble @@ -24,5 +16,5 @@ A tibble } \description{ This function condenses all A&E activity to a single category - compare -\code{get_detailed_pods()} which \emph{keeps} all A&E categories +\link{get_detailed_pods} which \emph{keeps} all A&E categories } diff --git a/man/get_outputs_gh_file.Rd b/man/get_outputs_gh_file.Rd deleted file mode 100644 index 807b366..0000000 --- a/man/get_outputs_gh_file.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/get_github_file.R -\name{get_outputs_gh_file} -\alias{get_outputs_gh_file} -\title{Read in a file from the NHP Outputs app GitHub repo} -\usage{ -get_outputs_gh_file(file, folder = "inst") -} -\arguments{ -\item{file}{string. The name of the file to read in} - -\item{folder}{string. The folder where the file is located. \code{"inst"} by -default. Set to \code{""} to use the root folder of the repo.} -} -\value{ -The file contents as a stream, to be passed to a reader function -} -\description{ -Read in a file from the NHP Outputs app GitHub repo -} -\keyword{internal} diff --git a/man/get_outputs_gh_url.Rd b/man/get_outputs_gh_url.Rd new file mode 100644 index 0000000..201e1ab --- /dev/null +++ b/man/get_outputs_gh_url.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_github_file.R +\name{get_outputs_gh_url} +\alias{get_outputs_gh_url} +\title{Get the direct URL to a file in the NHP Outputs GitHub repo} +\usage{ +get_outputs_gh_url(...) +} +\arguments{ +\item{...}{Pass the name of the file in via \code{...}} +} +\description{ +Get the direct URL to a file in the NHP Outputs GitHub repo +} +\keyword{internal} diff --git a/man/get_su_gh_file.Rd b/man/get_su_gh_file.Rd new file mode 100644 index 0000000..221b84c --- /dev/null +++ b/man/get_su_gh_file.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_github_file.R +\name{get_su_gh_file} +\alias{get_su_gh_file} +\title{Read in a file from a Strategy Unit GitHub repo} +\usage{ +get_su_gh_file(repo, folder, file) +} +\arguments{ +\item{repo}{string. The name of the repository in which to find the file} + +\item{folder}{string. The folder where the file is located. Set to \code{""} to +use the root folder of the repo.} + +\item{file}{string. The name of the file to read in} +} +\value{ +The URL to the raw file contents, to be passed to a reader function +} +\description{ +Read in a file from a Strategy Unit GitHub repo +} +\keyword{internal} diff --git a/man/get_tpma_label_lookup.Rd b/man/get_tpma_label_lookup.Rd index f83148e..dbba986 100644 --- a/man/get_tpma_label_lookup.Rd +++ b/man/get_tpma_label_lookup.Rd @@ -4,19 +4,11 @@ \alias{get_tpma_label_lookup} \title{Prepare a lookup table for all current TPMAs} \usage{ -get_tpma_label_lookup(use_local = FALSE) -} -\arguments{ -\item{use_local}{logical. Whether to use a local file (internal to the -reskit package) or attempt to pull the lookup file from GitHub. Default is -\code{FALSE}, meaning it will use the GitHub route. If you want to always use a -local file (for example, for fully offline working), you can set the -\code{reskit.local.lookups} option to \code{TRUE} using -\code{options(reskit.local.lookups = TRUE)} or \code{withr::with_options()}} +get_tpma_label_lookup() } \value{ -A 4-column tibble, with columns \code{activity_type}, \code{change_factor}, -\code{strategy} and \code{tpma_label} +A 4-column tibble, with columns \code{strategy}, \code{activity_type}, +\code{change_factor} and \code{tpma_label} } \description{ Prepare a lookup table for all current TPMAs diff --git a/man/get_tpmas_gh_file.Rd b/man/get_tpmas_gh_file.Rd deleted file mode 100644 index bd27243..0000000 --- a/man/get_tpmas_gh_file.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/get_github_file.R -\name{get_tpmas_gh_file} -\alias{get_tpmas_gh_file} -\title{Read in a file from the TPMAs GitHub repo} -\usage{ -get_tpmas_gh_file(file, folder = "reference") -} -\arguments{ -\item{file}{string. The name of the file to read in} - -\item{folder}{string. The folder where the file is located. \code{"reference"} by -default. Set to \code{""} to use the root folder of the repo.} -} -\value{ -The file contents as a stream, to be passed to a reader function -} -\description{ -Read in a file from the TPMAs GitHub repo -} -\keyword{internal} diff --git a/man/get_tpmas_gh_url.Rd b/man/get_tpmas_gh_url.Rd new file mode 100644 index 0000000..76ac56e --- /dev/null +++ b/man/get_tpmas_gh_url.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_github_file.R +\name{get_tpmas_gh_url} +\alias{get_tpmas_gh_url} +\title{Get the direct URL to a file in the TPMAs GitHub repo} +\usage{ +get_tpmas_gh_url(...) +} +\arguments{ +\item{...}{Pass the name of the file in via \code{...}} +} +\description{ +Get the direct URL to a file in the TPMAs GitHub repo +} +\keyword{internal} diff --git a/man/read_pods_lookup.Rd b/man/read_pods_lookup.Rd new file mode 100644 index 0000000..e75fff0 --- /dev/null +++ b/man/read_pods_lookup.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_github_file.R +\name{read_pods_lookup} +\alias{read_pods_lookup} +\title{Read the pods lookup table from a YAML file in the NHP Outputs repo} +\usage{ +read_pods_lookup(file = "golem-config.yml") +} +\description{ +Read the pods lookup table from a YAML file in the NHP Outputs repo +} diff --git a/man/read_tpmas_lookup.Rd b/man/read_tpmas_lookup.Rd new file mode 100644 index 0000000..64e0570 --- /dev/null +++ b/man/read_tpmas_lookup.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_github_file.R +\name{read_tpmas_lookup} +\alias{read_tpmas_lookup} +\title{Read the TPMAs lookup table from a CSV file in the TPMAs repo} +\usage{ +read_tpmas_lookup(file = "tpma-lookup.csv") +} +\description{ +Read the TPMAs lookup table from a CSV file in the TPMAs repo +}