From 016d2a746b78ae55136885054fb482c6671f7f9a Mon Sep 17 00:00:00 2001 From: Alex Reinhart Date: Fri, 15 Sep 2023 15:16:56 -0400 Subject: [PATCH 1/3] Rename get_auth_key, add set_api_key, document Moves the API key documentation to a central spot that is easy to point users to. Edits the warning message to point here, so we don't repeat the key advice in different places. Expand description of how to set options or environment variables. --- NAMESPACE | 3 +- R/auth.R | 67 ++++++++++++++++++++++------- R/epidatr-package.R | 5 +++ R/request.R | 4 +- _pkgdown.yml | 2 +- man/epidatr-package.Rd | 7 +++ man/get_api_key.Rd | 58 +++++++++++++++++++++++++ man/get_auth_key.Rd | 15 ------- tests/testthat/generate_test_data.R | 2 +- tests/testthat/test-auth.R | 9 ++-- vignettes/epidatr.Rmd | 10 +---- 11 files changed, 133 insertions(+), 49 deletions(-) create mode 100644 man/get_api_key.Rd delete mode 100644 man/get_auth_key.Rd diff --git a/NAMESPACE b/NAMESPACE index 5e0849a0..5a9f2939 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -15,7 +15,7 @@ export(disable_cache) export(epirange) export(fetch) export(fetch_args_list) -export(get_auth_key) +export(get_api_key) export(pub_covid_hosp_facility) export(pub_covid_hosp_facility_lookup) export(pub_covid_hosp_state_timeseries) @@ -44,6 +44,7 @@ export(pvt_norostat) export(pvt_quidel) export(pvt_sensors) export(pvt_twitter) +export(set_api_key) export(set_cache) import(cachem) import(glue) diff --git a/R/auth.R b/R/auth.R index 1dbaaf43..95fcfe70 100644 --- a/R/auth.R +++ b/R/auth.R @@ -1,36 +1,71 @@ -#' Getting the API key +#' Get and set API keys #' -#' @description -#' Get the API key from the environment variable `DELPHI_EPIDATA_KEY` or -#' `getOption("delphi.epidata.key")`. +#' Get and set the API key used to make requests to the Epidata API. Without a +#' key, requests may be subject to rate limits and other limitations. #' -#' @return The API key as a string or "". +#' We recommend you register for an API key. While most endpoints are available +#' without one, there are [limits on API usage for anonymous +#' users](https://cmu-delphi.github.io/delphi-epidata/api/api_keys.html), +#' including a rate limit. If you regularly request large amounts of data, +#' please consider [registering for an API +#' key](https://api.delphi.cmu.edu/epidata/admin/registration_form). #' +#' API keys are strings and can be set in two ways. If the environment variable +#' `DELPHI_EPIDATA_KEY` is set, it will be used automatically. Environment +#' variables can be set either in the shell or by editing your `.Renviron` file, +#' which will ensure the setting applies to all R sessions. See `?Startup` for a +#' description of `Renviron` files and where they can be placed. +#' +#' Alternately, the API key can be set from within a session by using +#' `set_api_key()`, which sets the R option `delphi.epidata.key` using +#' `options()`. If this option is set, it is used in preference to the +#' environment variable, so you may change keys within an R session. R options +#' are not preserved between sessions, so `set_api_key()` must be run every time +#' you open R. Alternately, you can have R set the option at startup by adding +#' it to your `.Rprofile`; see `?Startup` for a description of `Rprofile` files +#' and where they can be placed. +#' +#' Once an API key is set, it is automatically used for all requests made by +#' functions in this package. +#' +#' @return For `get_api_key()`, returns the current API key as a string, or +#' `""` if none is set. +#' +#' @seealso [usethis::edit_r_environ()] to automatically edit the `.Renviron` +#' file; [usethis::edit_r_profile()] to automatically edit the `.Rprofile` +#' file +#' +#' @references Delphi Epidata API Keys documentation. +#' +#' +#' Delphi Epidata API Registration Form. +#' #' @export -get_auth_key <- function() { - key <- Sys.getenv("DELPHI_EPIDATA_KEY", unset = "") +get_api_key <- function() { + key <- getOption("delphi.epidata.key", default = "") if (key != "") { return(key) } - key <- getOption("delphi.epidata.key", default = "") + key <- Sys.getenv("DELPHI_EPIDATA_KEY", unset = "") if (key != "") { return(key) } cli::cli_warn( c( - "No API key found. You will be limited to non-complex queries and encounter rate limits if you proceed. - To avoid this, you can get your key by registering - at https://api.delphi.cmu.edu/epidata/admin/registration_form and then:", - "i" = "set the environment variable DELPHI_EPIDATA_KEY", - "i" = "set the option 'delphi.epidata.key'", - "", - "To save your key for later sessions (and hide it from your code), you can edit your .Renviron file with:", - "i" = "usethis::edit_r_environ()" + "No API key found. You will be limited to non-complex queries and encounter rate limits if you proceed.", + "i" = "See {.help set_api_key} for details on obtaining and setting API keys." ), .frequency = "regularly", .frequency_id = "delphi.epidata.key" ) return("") } + +#' @rdname get_api_key +#' @param key API key to use for future requests +#' @export +set_api_key <- function(key) { + options(delphi.epidata.key = key) +} diff --git a/R/epidatr-package.R b/R/epidatr-package.R index 8d272a30..ad1ed5da 100644 --- a/R/epidatr-package.R +++ b/R/epidatr-package.R @@ -1,3 +1,8 @@ +#' @section Package options: +#' +#' The `delphi.epidata.key` option specifies the API key to be used when making +#' requests to the Epidata API. +#' #' @keywords internal #' @include cache.R "_PACKAGE" diff --git a/R/request.R b/R/request.R index 276df8df..d6fd5ea3 100644 --- a/R/request.R +++ b/R/request.R @@ -29,7 +29,7 @@ do_request <- function(url, params, timeout_seconds = 30) { query = params, terminate_on = c(400, 401, 403, 405, 414, 500), http_headers, - httr::authenticate("epidata", get_auth_key()), + httr::authenticate("epidata", get_api_key()), httr::timeout(timeout_seconds) ) if (res$status_code == 414) { @@ -39,7 +39,7 @@ do_request <- function(url, params, timeout_seconds = 30) { encode = "form", terminate_on = c(400, 401, 403, 405, 414, 500), http_headers, - httr::authenticate("epidata", get_auth_key()) + httr::authenticate("epidata", get_api_key()) ) } res diff --git a/_pkgdown.yml b/_pkgdown.yml index 26cf0d2b..3dd28794 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -36,7 +36,7 @@ reference: - title: Configuration and utilities desc: Set API keys and handle API data types - contents: - - get_auth_key + - get_api_key - avail_endpoints - epirange - timeset diff --git a/man/epidatr-package.Rd b/man/epidatr-package.Rd index b2e49714..9521ea06 100644 --- a/man/epidatr-package.Rd +++ b/man/epidatr-package.Rd @@ -8,6 +8,13 @@ \description{ The Delphi 'Epidata' API provides real-time access to epidemiological surveillance data for influenza, 'COVID-19', and other diseases for the USA at various geographical resolutions, both from official government sources such as the Center for Disease Control (CDC) and Google Trends and private partners such as Facebook and Change 'Healthcare'. It is built and maintained by the Carnegie Mellon University Delphi research group. To cite this API: David C. Farrow, Logan C. Brooks, Aaron 'Rumack', Ryan J. 'Tibshirani', 'Roni' 'Rosenfeld' (2015). Delphi 'Epidata' API. \url{https://github.com/cmu-delphi/delphi-epidata}. } +\section{Package options}{ + + +The \code{delphi.epidata.key} option specifies the API key to be used when making +requests to the Epidata API. +} + \seealso{ Useful links: \itemize{ diff --git a/man/get_api_key.Rd b/man/get_api_key.Rd new file mode 100644 index 00000000..40774c66 --- /dev/null +++ b/man/get_api_key.Rd @@ -0,0 +1,58 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{get_api_key} +\alias{get_api_key} +\alias{set_api_key} +\title{Get and set API keys} +\usage{ +get_api_key() + +set_api_key(key) +} +\arguments{ +\item{key}{API key to use for future requests} +} +\value{ +For \code{get_api_key()}, returns the current API key as a string, or +\code{""} if none is set. +} +\description{ +Get and set the API key used to make requests to the Epidata API. Without a +key, requests may be subject to rate limits and other limitations. +} +\details{ +We recommend you register for an API key. While most endpoints are available +without one, there are \href{https://cmu-delphi.github.io/delphi-epidata/api/api_keys.html}{limits on API usage for anonymous users}, +including a rate limit. If you regularly request large amounts of data, +please consider \href{https://api.delphi.cmu.edu/epidata/admin/registration_form}{registering for an API key}. + +API keys are strings and can be set in two ways. If the environment variable +\code{DELPHI_EPIDATA_KEY} is set, it will be used automatically. Environment +variables can be set either in the shell or by editing your \code{.Renviron} file, +which will ensure the setting applies to all R sessions. See \code{?Startup} for a +description of \code{Renviron} files and where they can be placed. + +Alternately, the API key can be set from within a session by using +\code{set_api_key()}, which sets the R option \code{delphi.epidata.key} using +\code{options()}. If this option is set, it is used in preference to the +environment variable, so you may change keys within an R session. R options +are not preserved between sessions, so \code{set_api_key()} must be run every time +you open R. Alternately, you can have R set the option at startup by adding +it to your \code{.Rprofile}; see \code{?Startup} for a description of \code{Rprofile} files +and where they can be placed. + +Once an API key is set, it is automatically used for all requests made by +functions in this package. +} +\references{ +Delphi Epidata API Keys documentation. +\url{https://cmu-delphi.github.io/delphi-epidata/api/api_keys.html} + +Delphi Epidata API Registration Form. +\url{https://api.delphi.cmu.edu/epidata/admin/registration_form} +} +\seealso{ +\code{\link[usethis:edit]{usethis::edit_r_environ()}} to automatically edit the \code{.Renviron} +file; \code{\link[usethis:edit]{usethis::edit_r_profile()}} to automatically edit the \code{.Rprofile} +file +} diff --git a/man/get_auth_key.Rd b/man/get_auth_key.Rd deleted file mode 100644 index 65808781..00000000 --- a/man/get_auth_key.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/auth.R -\name{get_auth_key} -\alias{get_auth_key} -\title{Getting the API key} -\usage{ -get_auth_key() -} -\value{ -The API key as a string or "". -} -\description{ -Get the API key from the environment variable \code{DELPHI_EPIDATA_KEY} or -\code{getOption("delphi.epidata.key")}. -} diff --git a/tests/testthat/generate_test_data.R b/tests/testthat/generate_test_data.R index 95032fba..1aac8393 100644 --- a/tests/testthat/generate_test_data.R +++ b/tests/testthat/generate_test_data.R @@ -33,5 +33,5 @@ response <- httr::RETRY("GET", query = list(), terminate_on = c(400, 401, 403, 405, 414, 500), http_headers, - httr::authenticate("epidata", get_auth_key()) + httr::authenticate("epidata", get_api_key()) ) %>% readr::write_rds(testthat::test_path("data/test-do_request-httpbin.rds")) diff --git a/tests/testthat/test-auth.R b/tests/testthat/test-auth.R index 3aa07cd3..9d9ab391 100644 --- a/tests/testthat/test-auth.R +++ b/tests/testthat/test-auth.R @@ -1,15 +1,14 @@ -test_that("get_auth_key", { +test_that("get_api_key", { withr::with_envvar(c(DELPHI_EPIDATA_KEY = "epidata_key_from_envvar"), { withr::with_options(list(delphi.epidata.key = "epidata_key_from_options"), { - # envvar takes precedence over option (characterization test; we don't - # guarantee this in docs): - expect_identical(get_auth_key(), "epidata_key_from_envvar") + # option takes precedence over environment variable + expect_identical(get_api_key(), "epidata_key_from_options") }) }) withr::with_envvar(c(DELPHI_EPIDATA_KEY = NA_character_), { withr::with_options(list(delphi.epidata.key = "epidata_key_from_options"), { # option by itself works: - expect_identical(get_auth_key(), "epidata_key_from_options") + expect_identical(get_api_key(), "epidata_key_from_options") }) }) }) diff --git a/vignettes/epidatr.Rmd b/vignettes/epidatr.Rmd index a2913b38..f3120468 100644 --- a/vignettes/epidatr.Rmd +++ b/vignettes/epidatr.Rmd @@ -23,14 +23,8 @@ regions. We recommend you register for an API key. While most endpoints are available without one, there are [limits on API usage for anonymous users](https://cmu-delphi.github.io/delphi-epidata/api/api_keys.html), including -a rate limit. If you regularly request large amounts of data, please consider -[registering for an API -key](https://api.delphi.cmu.edu/epidata/admin/registration_form). You can then -specify this key by either - -- setting the environment variable `DELPHI_EPIDATA_KEY`, such as by editing your - `.Renviron` file -- setting the option `delphi.epidata.key` using `options()` +a rate limit. See `set_api_key()` for details on how to obtain an API key and +set this package to use it. ## Basic Usage From 9e971e49e4f182b2bc712ec282c49633c0ab1f2c Mon Sep 17 00:00:00 2001 From: Alex Reinhart Date: Fri, 15 Sep 2023 15:50:32 -0400 Subject: [PATCH 2/3] Update README explanation of how to get keys --- README.Rmd | 14 ++++++-------- README.md | 18 ++++++++---------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/README.Rmd b/README.Rmd index 821c6690..0233fc8a 100644 --- a/README.Rmd +++ b/README.Rmd @@ -79,14 +79,12 @@ The Delphi API requires a (free) API key for full functionality. To generate your key, register for a pseudo-anonymous account [here](https://api.delphi.cmu.edu/epidata/admin/registration_form) and see more discussion on the [general API -website](https://cmu-delphi.github.io/delphi-epidata/api/api_keys.html). The -`epidatr` client will automatically look for this key in the R option -`delphi.epidata.key` or in the environment variable -`DELPHI_EPIDATA_KEY`. We recommend storing your key in `.Renviron` file, which R -will read by default. - -Note that for the time being, the private endpoints (i.e. those prefixed with -`pvt`) will require a separate key that needs to be passed as an argument. +website](https://cmu-delphi.github.io/delphi-epidata/api/api_keys.html). See the +`set_api_key()` function documentation for details on how to use your API key. + +Note that the private endpoints (i.e. those prefixed with `pvt_`) require a +separate key that needs to be passed as an argument. These endpoints require +specific data use agreements to access. [mit-image]: https://img.shields.io/badge/License-MIT-yellow.svg [mit-url]: https://opensource.org/license/mit/ diff --git a/README.md b/README.md index b3423f1f..f04b7be9 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ provides real-time access to epidemiological surveillance data for influenza, COVID-19, and other diseases for the USA at various geographical resolutions, both from official government sources such as the [Center for Disease Control -(CDC)](https://www.cdc.gov/datastatistics/index.html), public sources such as [Google -Trends](https://cmu-delphi.github.io/delphi-epidata/api/covidcast-signals/google-symptoms.html), +(CDC)](https://www.cdc.gov/datastatistics/index.html) and [Google +Trends](https://cmu-delphi.github.io/delphi-epidata/api/covidcast-signals/google-symptoms.html) and private partners such as [Facebook](https://delphi.cmu.edu/blog/2020/08/26/covid-19-symptom-surveys-through-facebook/) and [Change Healthcare](https://www.changehealthcare.com/). It is built @@ -104,14 +104,12 @@ generate your key, register for a pseudo-anonymous account [here](https://api.delphi.cmu.edu/epidata/admin/registration_form) and see more discussion on the [general API website](https://cmu-delphi.github.io/delphi-epidata/api/api_keys.html). -The `epidatr` client will automatically look for this key in the R -option `delphi.epidata.key` or in the environment variable -`DELPHI_EPIDATA_KEY`. We recommend storing your key in `.Renviron` file, -which R will read by default. - -Note that for the time being, the private endpoints (i.e. those prefixed -with `pvt`) will require a separate key that needs to be passed as an -argument. +See the `set_api_key()` function documentation for details on how to use +your API key. + +Note that the private endpoints (i.e. those prefixed with `pvt_`) +require a separate key that needs to be passed as an argument. These +endpoints require specific data use agreements to access. ## Get updates From 94024b11ede93c6185131ed8e63e23a9824827cf Mon Sep 17 00:00:00 2001 From: capnrefsmmat Date: Fri, 15 Sep 2023 19:52:37 +0000 Subject: [PATCH 3/3] docs: document (GHA) --- man/get_api_key.Rd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/get_api_key.Rd b/man/get_api_key.Rd index 40774c66..18f7ae65 100644 --- a/man/get_api_key.Rd +++ b/man/get_api_key.Rd @@ -52,7 +52,7 @@ Delphi Epidata API Registration Form. \url{https://api.delphi.cmu.edu/epidata/admin/registration_form} } \seealso{ -\code{\link[usethis:edit]{usethis::edit_r_environ()}} to automatically edit the \code{.Renviron} -file; \code{\link[usethis:edit]{usethis::edit_r_profile()}} to automatically edit the \code{.Rprofile} +\code{\link[usethis:edit_r_environ]{usethis::edit_r_environ()}} to automatically edit the \code{.Renviron} +file; \code{\link[usethis:edit_r_profile]{usethis::edit_r_profile()}} to automatically edit the \code{.Rprofile} file }